s3/winbindd: use parse_domain_user instead of parse_domain_user_fstr
[Samba.git] / source3 / winbindd / winbindd_util.c
blob443f7c1a108b99767b71e062f15e5ec1543ab102
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 static bool add_trusted_domains_dc(void);
52 /* The list of trusted domains. Note that the list can be deleted and
53 recreated using the init_domain_list() function so pointers to
54 individual winbindd_domain structures cannot be made. Keep a copy of
55 the domain name instead. */
57 static struct winbindd_domain *_domain_list = NULL;
59 struct winbindd_domain *domain_list(void)
61 /* Initialise list */
63 if ((!_domain_list) && (!init_domain_list())) {
64 smb_panic("Init_domain_list failed");
67 return _domain_list;
70 /* Free all entries in the trusted domain list */
72 static void free_domain_list(void)
74 struct winbindd_domain *domain = _domain_list;
76 while(domain) {
77 struct winbindd_domain *next = domain->next;
79 DLIST_REMOVE(_domain_list, domain);
80 TALLOC_FREE(domain);
81 domain = next;
85 /**
86 * Iterator for winbindd's domain list.
87 * To be used (e.g.) in tevent based loops.
89 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
91 if (domain == NULL) {
92 domain = domain_list();
93 } else {
94 domain = domain->next;
97 if ((domain != NULL) &&
98 (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
99 sid_check_is_our_sam(&domain->sid))
101 domain = domain->next;
104 return domain;
107 static bool is_internal_domain(const struct dom_sid *sid)
109 if (sid == NULL)
110 return False;
112 return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
115 /* Add a trusted domain to our list of domains.
116 If the domain already exists in the list,
117 return it and don't re-initialize. */
119 static NTSTATUS add_trusted_domain(const char *domain_name,
120 const char *dns_name,
121 const struct dom_sid *sid,
122 uint32_t trust_type,
123 uint32_t trust_flags,
124 uint32_t trust_attribs,
125 enum netr_SchannelType secure_channel_type,
126 struct winbindd_domain *routing_domain,
127 struct winbindd_domain **_d)
129 struct winbindd_domain *domain = NULL;
130 int role = lp_server_role();
131 struct dom_sid_buf buf;
133 if (is_null_sid(sid)) {
134 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
135 return NT_STATUS_INVALID_PARAMETER;
138 if (secure_channel_type == SEC_CHAN_NULL && !is_allowed_domain(domain_name)) {
139 return NT_STATUS_NO_SUCH_DOMAIN;
143 * We can't call domain_list() as this function is called from
144 * init_domain_list() and we'll get stuck in a loop.
146 for (domain = _domain_list; domain; domain = domain->next) {
147 if (strequal(domain_name, domain->name)) {
148 break;
152 if (domain != NULL) {
153 struct winbindd_domain *check_domain = NULL;
155 for (check_domain = _domain_list;
156 check_domain != NULL;
157 check_domain = check_domain->next)
159 if (check_domain == domain) {
160 continue;
163 if (dom_sid_equal(&check_domain->sid, sid)) {
164 break;
168 if (check_domain != NULL) {
169 DBG_ERR("SID [%s] already used by domain [%s], "
170 "expected [%s]\n",
171 dom_sid_str_buf(sid, &buf),
172 check_domain->name,
173 domain->name);
174 return NT_STATUS_INVALID_PARAMETER;
178 if ((domain != NULL) && (dns_name != NULL)) {
179 struct winbindd_domain *check_domain = NULL;
181 for (check_domain = _domain_list;
182 check_domain != NULL;
183 check_domain = check_domain->next)
185 if (check_domain == domain) {
186 continue;
189 if (strequal(check_domain->alt_name, dns_name)) {
190 break;
194 if (check_domain != NULL) {
195 DBG_ERR("DNS name [%s] used by domain [%s], "
196 "expected [%s]\n",
197 dns_name, check_domain->name,
198 domain->name);
199 return NT_STATUS_INVALID_PARAMETER;
203 if (domain != NULL) {
204 *_d = domain;
205 return NT_STATUS_OK;
208 /* Create new domain entry */
209 domain = talloc_zero(NULL, struct winbindd_domain);
210 if (domain == NULL) {
211 return NT_STATUS_NO_MEMORY;
214 domain->children = talloc_zero_array(domain,
215 struct winbindd_child,
216 lp_winbind_max_domain_connections());
217 if (domain->children == NULL) {
218 TALLOC_FREE(domain);
219 return NT_STATUS_NO_MEMORY;
222 domain->queue = tevent_queue_create(domain, "winbind_domain");
223 if (domain->queue == NULL) {
224 TALLOC_FREE(domain);
225 return NT_STATUS_NO_MEMORY;
228 domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
229 if (domain->binding_handle == NULL) {
230 TALLOC_FREE(domain);
231 return NT_STATUS_NO_MEMORY;
234 domain->name = talloc_strdup(domain, domain_name);
235 if (domain->name == NULL) {
236 TALLOC_FREE(domain);
237 return NT_STATUS_NO_MEMORY;
240 if (dns_name != NULL) {
241 domain->alt_name = talloc_strdup(domain, dns_name);
242 if (domain->alt_name == NULL) {
243 TALLOC_FREE(domain);
244 return NT_STATUS_NO_MEMORY;
248 domain->backend = NULL;
249 domain->internal = is_internal_domain(sid);
250 domain->secure_channel_type = secure_channel_type;
251 domain->sequence_number = DOM_SEQUENCE_NONE;
252 domain->last_seq_check = 0;
253 domain->initialized = false;
254 domain->online = is_internal_domain(sid);
255 domain->domain_flags = trust_flags;
256 domain->domain_type = trust_type;
257 domain->domain_trust_attribs = trust_attribs;
258 domain->secure_channel_type = secure_channel_type;
259 domain->routing_domain = routing_domain;
260 sid_copy(&domain->sid, sid);
262 /* Is this our primary domain ? */
263 if (role == ROLE_DOMAIN_MEMBER) {
264 domain->primary = strequal(domain_name, lp_workgroup());
265 } else {
266 domain->primary = strequal(domain_name, get_global_sam_name());
269 if (domain->primary) {
270 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
271 domain->active_directory = true;
273 if (lp_security() == SEC_ADS) {
274 domain->active_directory = true;
276 } else if (!domain->internal) {
277 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
278 domain->active_directory = true;
282 domain->can_do_ncacn_ip_tcp = domain->active_directory;
284 /* Link to domain list */
285 DLIST_ADD_END(_domain_list, domain);
287 wcache_tdc_add_domain( domain );
289 setup_domain_child(domain);
291 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
292 domain->name, domain->alt_name,
293 dom_sid_str_buf(&domain->sid, &buf));
295 *_d = domain;
296 return NT_STATUS_OK;
299 bool set_routing_domain(struct winbindd_domain *domain,
300 struct winbindd_domain *routing_domain)
302 if (domain->routing_domain == NULL) {
303 domain->routing_domain = routing_domain;
304 return true;
306 if (domain->routing_domain != routing_domain) {
307 return false;
309 return true;
312 bool add_trusted_domain_from_auth(uint16_t validation_level,
313 struct info3_text *info3,
314 struct info6_text *info6)
316 struct winbindd_domain *domain = NULL;
317 struct dom_sid domain_sid;
318 const char *dns_domainname = NULL;
319 NTSTATUS status;
320 bool ok;
323 * We got a successful auth from a domain that might not yet be in our
324 * domain list. If we're a member we trust our DC who authenticated the
325 * user from that domain and add the domain to our list on-the-fly. If
326 * we're a DC we rely on configured trusts and don't add on-the-fly.
329 if (IS_DC) {
330 return true;
333 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
334 if (!ok) {
335 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
336 return false;
339 if (validation_level == 6) {
340 if (!strequal(info6->dns_domainname, "")) {
341 dns_domainname = info6->dns_domainname;
345 status = add_trusted_domain(info3->logon_dom,
346 dns_domainname,
347 &domain_sid,
349 NETR_TRUST_FLAG_OUTBOUND,
351 SEC_CHAN_NULL,
352 find_default_route_domain(),
353 &domain);
354 if (!NT_STATUS_IS_OK(status) &&
355 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
357 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
358 info3->logon_dom, info3->dom_sid);
359 return false;
362 return true;
365 bool domain_is_forest_root(const struct winbindd_domain *domain)
367 const uint32_t fr_flags =
368 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
370 return ((domain->domain_flags & fr_flags) == fr_flags);
373 /********************************************************************
374 rescan our domains looking for new trusted domains
375 ********************************************************************/
377 struct trustdom_state {
378 struct winbindd_domain *domain;
379 struct netr_DomainTrustList trusts;
382 static void trustdom_list_done(struct tevent_req *req);
383 static void rescan_forest_root_trusts( void );
384 static void rescan_forest_trusts( void );
386 static void add_trusted_domains( struct winbindd_domain *domain )
388 struct tevent_context *ev = global_event_context();
389 struct trustdom_state *state;
390 struct tevent_req *req;
391 const char *client_name = NULL;
392 pid_t client_pid;
394 state = talloc_zero(NULL, struct trustdom_state);
395 if (state == NULL) {
396 DEBUG(0, ("talloc failed\n"));
397 return;
399 state->domain = domain;
401 /* Called from timer, not from a real client */
402 client_name = getprogname();
403 client_pid = getpid();
405 req = dcerpc_wbint_ListTrustedDomains_send(state,
407 dom_child_handle(domain),
408 client_name,
409 client_pid,
410 &state->trusts);
411 if (req == NULL) {
412 DBG_ERR("dcerpc_wbint_ListTrustedDomains_send failed\n");
413 TALLOC_FREE(state);
414 return;
416 tevent_req_set_callback(req, trustdom_list_done, state);
419 static void trustdom_list_done(struct tevent_req *req)
421 struct trustdom_state *state = tevent_req_callback_data(
422 req, struct trustdom_state);
423 bool within_forest = false;
424 NTSTATUS status, result;
425 uint32_t i;
428 * Only when we enumerate our primary domain
429 * or our forest root domain, we should keep
430 * the NETR_TRUST_FLAG_IN_FOREST flag, in
431 * all other cases we need to clear it as the domain
432 * is not part of our forest.
434 if (state->domain->primary) {
435 within_forest = true;
436 } else if (domain_is_forest_root(state->domain)) {
437 within_forest = true;
440 status = dcerpc_wbint_ListTrustedDomains_recv(req, state, &result);
441 if (any_nt_status_not_ok(status, result, &status)) {
442 DBG_WARNING("Could not receive trusts for domain %s: %s-%s\n",
443 state->domain->name, nt_errstr(status),
444 nt_errstr(result));
445 TALLOC_FREE(state);
446 return;
449 for (i=0; i<state->trusts.count; i++) {
450 struct netr_DomainTrust *trust = &state->trusts.array[i];
451 struct winbindd_domain *domain = NULL;
453 if (!within_forest) {
454 trust->trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
457 if (!state->domain->primary) {
458 trust->trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
462 * We always call add_trusted_domain() cause on an existing
463 * domain structure, it will update the SID if necessary.
464 * This is important because we need the SID for sibling
465 * domains.
467 status = add_trusted_domain(trust->netbios_name,
468 trust->dns_name,
469 trust->sid,
470 trust->trust_type,
471 trust->trust_flags,
472 trust->trust_attributes,
473 SEC_CHAN_NULL,
474 find_default_route_domain(),
475 &domain);
476 if (!NT_STATUS_IS_OK(status) &&
477 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
479 DBG_NOTICE("add_trusted_domain returned %s\n",
480 nt_errstr(status));
481 return;
486 Cases to consider when scanning trusts:
487 (a) we are calling from a child domain (primary && !forest_root)
488 (b) we are calling from the root of the forest (primary && forest_root)
489 (c) we are calling from a trusted forest domain (!primary
490 && !forest_root)
493 if (state->domain->primary) {
494 /* If this is our primary domain and we are not in the
495 forest root, we have to scan the root trusts first */
497 if (!domain_is_forest_root(state->domain))
498 rescan_forest_root_trusts();
499 else
500 rescan_forest_trusts();
502 } else if (domain_is_forest_root(state->domain)) {
503 /* Once we have done root forest trust search, we can
504 go on to search the trusted forests */
506 rescan_forest_trusts();
509 TALLOC_FREE(state);
511 return;
514 /********************************************************************
515 Scan the trusts of our forest root
516 ********************************************************************/
518 static void rescan_forest_root_trusts( void )
520 struct winbindd_tdc_domain *dom_list = NULL;
521 size_t num_trusts = 0;
522 size_t i;
523 NTSTATUS status;
525 /* The only transitive trusts supported by Windows 2003 AD are
526 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
527 first two are handled in forest and listed by
528 DsEnumerateDomainTrusts(). Forest trusts are not so we
529 have to do that ourselves. */
531 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
532 return;
534 for ( i=0; i<num_trusts; i++ ) {
535 struct winbindd_domain *d = NULL;
537 /* Find the forest root. Don't necessarily trust
538 the domain_list() as our primary domain may not
539 have been initialized. */
541 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
542 continue;
545 /* Here's the forest root */
547 d = find_domain_from_name_noinit( dom_list[i].domain_name );
548 if (d == NULL) {
549 status = add_trusted_domain(dom_list[i].domain_name,
550 dom_list[i].dns_name,
551 &dom_list[i].sid,
552 dom_list[i].trust_type,
553 dom_list[i].trust_flags,
554 dom_list[i].trust_attribs,
555 SEC_CHAN_NULL,
556 find_default_route_domain(),
557 &d);
559 if (!NT_STATUS_IS_OK(status) &&
560 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
562 DBG_ERR("add_trusted_domain returned %s\n",
563 nt_errstr(status));
564 return;
567 if (d == NULL) {
568 continue;
571 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
572 "for domain tree root %s (%s)\n",
573 d->name, d->alt_name ));
575 d->domain_flags = dom_list[i].trust_flags;
576 d->domain_type = dom_list[i].trust_type;
577 d->domain_trust_attribs = dom_list[i].trust_attribs;
579 add_trusted_domains( d );
581 break;
584 TALLOC_FREE( dom_list );
586 return;
589 /********************************************************************
590 scan the transitive forest trusts (not our own)
591 ********************************************************************/
594 static void rescan_forest_trusts( void )
596 struct winbindd_domain *d = NULL;
597 struct winbindd_tdc_domain *dom_list = NULL;
598 size_t num_trusts = 0;
599 size_t i;
600 NTSTATUS status;
602 /* The only transitive trusts supported by Windows 2003 AD are
603 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
604 first two are handled in forest and listed by
605 DsEnumerateDomainTrusts(). Forest trusts are not so we
606 have to do that ourselves. */
608 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
609 return;
611 for ( i=0; i<num_trusts; i++ ) {
612 uint32_t flags = dom_list[i].trust_flags;
613 uint32_t type = dom_list[i].trust_type;
614 uint32_t attribs = dom_list[i].trust_attribs;
616 d = find_domain_from_name_noinit( dom_list[i].domain_name );
618 /* ignore our primary and internal domains */
620 if ( d && (d->internal || d->primary ) )
621 continue;
623 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
624 (type == LSA_TRUST_TYPE_UPLEVEL) &&
625 (attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
627 /* add the trusted domain if we don't know
628 about it */
630 if (d == NULL) {
631 status = add_trusted_domain(
632 dom_list[i].domain_name,
633 dom_list[i].dns_name,
634 &dom_list[i].sid,
635 type,
636 flags,
637 attribs,
638 SEC_CHAN_NULL,
639 find_default_route_domain(),
640 &d);
641 if (!NT_STATUS_IS_OK(status) &&
642 NT_STATUS_EQUAL(status,
643 NT_STATUS_NO_SUCH_DOMAIN))
645 DBG_ERR("add_trusted_domain: %s\n",
646 nt_errstr(status));
647 return;
651 if (d == NULL) {
652 continue;
655 DEBUG(10,("Following trust path for domain %s (%s)\n",
656 d->name, d->alt_name ));
657 add_trusted_domains( d );
661 TALLOC_FREE( dom_list );
663 return;
666 /*********************************************************************
667 The process of updating the trusted domain list is a three step
668 async process:
669 (a) ask our domain
670 (b) ask the root domain in our forest
671 (c) ask a DC in any Win2003 trusted forests
672 *********************************************************************/
674 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
675 struct timeval now, void *private_data)
677 TALLOC_FREE(te);
679 /* I used to clear the cache here and start over but that
680 caused problems in child processes that needed the
681 trust dom list early on. Removing it means we
682 could have some trusted domains listed that have been
683 removed from our primary domain's DC until a full
684 restart. This should be ok since I think this is what
685 Windows does as well. */
687 /* this will only add new domains we didn't already know about
688 in the domain_list()*/
690 add_trusted_domains( find_our_domain() );
692 te = tevent_add_timer(
693 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
694 rescan_trusted_domains, NULL);
696 * If te == NULL, there's not much we can do here. Don't fail, the
697 * only thing we miss is new trusted domains.
700 return;
703 static void wbd_ping_dc_done(struct tevent_req *subreq);
705 void winbindd_ping_offline_domains(struct tevent_context *ev,
706 struct tevent_timer *te,
707 struct timeval now,
708 void *private_data)
710 struct winbindd_domain *domain = NULL;
712 TALLOC_FREE(te);
714 for (domain = domain_list(); domain != NULL; domain = domain->next) {
715 DBG_DEBUG("Domain %s is %s\n",
716 domain->name,
717 domain->online ? "online" : "offline");
719 if (get_global_winbindd_state_offline()) {
720 DBG_DEBUG("We are globally offline, do nothing.\n");
721 break;
724 if (domain->online ||
725 domain->check_online_event != NULL ||
726 domain->secure_channel_type == SEC_CHAN_NULL) {
727 continue;
730 winbindd_flush_negative_conn_cache(domain);
732 domain->check_online_event =
733 dcerpc_wbint_PingDc_send(domain,
735 dom_child_handle(domain),
736 &domain->ping_dcname);
737 if (domain->check_online_event == NULL) {
738 DBG_WARNING("Failed to schedule ping, no-memory\n");
739 continue;
742 tevent_req_set_callback(domain->check_online_event,
743 wbd_ping_dc_done, domain);
746 te = tevent_add_timer(ev,
747 NULL,
748 timeval_current_ofs(lp_winbind_reconnect_delay(),
750 winbindd_ping_offline_domains,
751 NULL);
752 if (te == NULL) {
753 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
756 return;
759 static void wbd_ping_dc_done(struct tevent_req *subreq)
761 struct winbindd_domain *domain =
762 tevent_req_callback_data(subreq,
763 struct winbindd_domain);
764 NTSTATUS status, result;
766 SMB_ASSERT(subreq == domain->check_online_event);
767 domain->check_online_event = NULL;
769 status = dcerpc_wbint_PingDc_recv(subreq, domain, &result);
770 TALLOC_FREE(subreq);
771 if (any_nt_status_not_ok(status, result, &status)) {
772 DBG_WARNING("dcerpc_wbint_PingDc_recv failed for domain: "
773 "%s - %s\n",
774 domain->name,
775 nt_errstr(status));
776 return;
779 DBG_DEBUG("dcerpc_wbint_PingDc_recv() succeeded, "
780 "domain: %s, dc-name: %s\n",
781 domain->name,
782 domain->ping_dcname);
784 talloc_free(discard_const(domain->ping_dcname));
785 domain->ping_dcname = NULL;
787 return;
790 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
791 void *private_data,
792 uint32_t msg_type,
793 struct server_id server_id,
794 size_t num_fds,
795 int *fds,
796 DATA_BLOB *data)
798 bool ok;
800 if (num_fds != 0) {
801 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
802 return;
805 DBG_NOTICE("Rescanning trusted domains\n");
807 ok = add_trusted_domains_dc();
808 if (!ok) {
809 DBG_ERR("Failed to reload trusted domains\n");
814 * We did not get the secret when we queried secrets.tdb, so read it
815 * from secrets.tdb and re-sync the databases
817 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
819 bool ok;
820 struct cli_credentials *creds;
821 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
822 NULL, domain, &creds);
823 if (!NT_STATUS_IS_OK(can_migrate)) {
824 DEBUG(0, ("Failed to fetch our own local AD domain join "
825 "password for winbindd's internal use, both from "
826 "secrets.tdb and secrets.ldb: %s\n",
827 nt_errstr(can_migrate)));
828 return false;
832 * NOTE: It is very unlikely we end up here if there is an
833 * oldpass, because a new password is created at
834 * classicupgrade, so this is not a concern.
836 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
837 NULL /* oldpass */,
838 cli_credentials_get_domain(creds),
839 cli_credentials_get_realm(creds),
840 cli_credentials_get_salt_principal(creds),
841 0, /* Supported enc types, unused */
842 &domain->sid,
843 cli_credentials_get_password_last_changed_time(creds),
844 cli_credentials_get_secure_channel_type(creds),
845 false /* do_delete: Do not delete */);
846 TALLOC_FREE(creds);
847 if (ok == false) {
848 DEBUG(0, ("Failed to write our own "
849 "local AD domain join password for "
850 "winbindd's internal use into secrets.tdb\n"));
851 return false;
853 return true;
856 static bool add_trusted_domains_dc(void)
858 struct winbindd_domain *domain = NULL;
859 struct pdb_trusted_domain **domains = NULL;
860 uint32_t num_domains = 0;
861 uint32_t i;
862 NTSTATUS status;
864 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
865 struct trustdom_info **ti = NULL;
867 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
868 if (!NT_STATUS_IS_OK(status)) {
869 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
870 nt_errstr(status));
871 return false;
874 for (i = 0; i < num_domains; i++) {
875 status = add_trusted_domain(ti[i]->name,
876 NULL,
877 &ti[i]->sid,
878 LSA_TRUST_TYPE_DOWNLEVEL,
879 NETR_TRUST_FLAG_OUTBOUND,
881 SEC_CHAN_DOMAIN,
882 NULL,
883 &domain);
884 if (!NT_STATUS_IS_OK(status)) {
885 DBG_NOTICE("add_trusted_domain returned %s\n",
886 nt_errstr(status));
887 return false;
891 return true;
894 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
895 if (!NT_STATUS_IS_OK(status)) {
896 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
897 nt_errstr(status));
898 return false;
901 for (i = 0; i < num_domains; i++) {
902 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
903 uint32_t trust_flags = 0;
905 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
906 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
909 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
910 sec_chan_type = SEC_CHAN_NULL;
913 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
914 trust_flags |= NETR_TRUST_FLAG_INBOUND;
916 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
917 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
919 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
920 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
923 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
925 * We don't support selective authentication yet.
927 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
928 "domain[%s/%s]\n",
929 domains[i]->netbios_name,
930 domains[i]->domain_name);
931 continue;
934 status = add_trusted_domain(domains[i]->netbios_name,
935 domains[i]->domain_name,
936 &domains[i]->security_identifier,
937 domains[i]->trust_type,
938 trust_flags,
939 domains[i]->trust_attributes,
940 sec_chan_type,
941 NULL,
942 &domain);
943 if (!NT_STATUS_IS_OK(status)) {
944 DBG_NOTICE("add_trusted_domain returned %s\n",
945 nt_errstr(status));
946 return false;
949 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
950 domain->active_directory = true;
952 domain->domain_type = domains[i]->trust_type;
953 domain->domain_trust_attribs = domains[i]->trust_attributes;
956 for (i = 0; i < num_domains; i++) {
957 struct ForestTrustInfo fti;
958 uint32_t fi;
959 enum ndr_err_code ndr_err;
960 struct winbindd_domain *routing_domain = NULL;
962 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
963 continue;
966 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
967 continue;
970 if (domains[i]->trust_forest_trust_info.length == 0) {
971 continue;
974 routing_domain = find_domain_from_name_noinit(
975 domains[i]->netbios_name);
976 if (routing_domain == NULL) {
977 DBG_ERR("Can't find winbindd domain [%s]\n",
978 domains[i]->netbios_name);
979 return false;
982 ndr_err = ndr_pull_struct_blob_all(
983 &domains[i]->trust_forest_trust_info,
984 talloc_tos(), &fti,
985 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
986 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
987 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
988 domains[i]->netbios_name,
989 ndr_map_error2string(ndr_err));
990 return false;
993 for (fi = 0; fi < fti.count; fi++) {
994 struct ForestTrustInfoRecord *rec =
995 &fti.records[fi].record;
996 struct ForestTrustDataDomainInfo *drec = NULL;
998 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
999 continue;
1001 drec = &rec->data.info;
1003 if (rec->flags & LSA_NB_DISABLED_MASK) {
1004 continue;
1007 if (rec->flags & LSA_SID_DISABLED_MASK) {
1008 continue;
1012 * TODO:
1013 * also try to find a matching
1014 * LSA_TLN_DISABLED_MASK ???
1017 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1018 if (domain != NULL) {
1019 continue;
1022 status = add_trusted_domain(drec->netbios_name.string,
1023 drec->dns_name.string,
1024 &drec->sid,
1025 LSA_TRUST_TYPE_UPLEVEL,
1026 NETR_TRUST_FLAG_OUTBOUND,
1028 SEC_CHAN_NULL,
1029 routing_domain,
1030 &domain);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 DBG_NOTICE("add_trusted_domain returned %s\n",
1033 nt_errstr(status));
1034 return false;
1036 if (domain == NULL) {
1037 continue;
1042 return true;
1046 /* Look up global info for the winbind daemon */
1047 bool init_domain_list(void)
1049 int role = lp_server_role();
1050 struct pdb_domain_info *pdb_domain_info = NULL;
1051 struct winbindd_domain *domain = NULL;
1052 NTSTATUS status;
1053 bool ok;
1055 /* Free existing list */
1056 free_domain_list();
1058 /* BUILTIN domain */
1060 status = add_trusted_domain("BUILTIN",
1061 NULL,
1062 &global_sid_Builtin,
1063 LSA_TRUST_TYPE_DOWNLEVEL,
1064 0, /* trust_flags */
1065 0, /* trust_attribs */
1066 SEC_CHAN_LOCAL,
1067 NULL,
1068 &domain);
1069 if (!NT_STATUS_IS_OK(status)) {
1070 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1071 nt_errstr(status));
1072 return false;
1075 /* Local SAM */
1078 * In case the passdb backend is passdb_dsdb the domain SID comes from
1079 * dsdb, not from secrets.tdb. As we use the domain SID in various
1080 * places, we must ensure the domain SID is migrated from dsdb to
1081 * secrets.tdb before get_global_sam_sid() is called the first time.
1083 * The migration is done as part of the passdb_dsdb initialisation,
1084 * calling pdb_get_domain_info() triggers it.
1086 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1088 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1089 uint32_t trust_flags;
1090 bool is_root;
1091 enum netr_SchannelType sec_chan_type;
1092 const char *account_name;
1093 struct samr_Password current_nt_hash;
1095 if (pdb_domain_info == NULL) {
1096 DEBUG(0, ("Failed to fetch our own local AD "
1097 "domain info from sam.ldb\n"));
1098 return false;
1101 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1102 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1103 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1104 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1106 is_root = strequal(pdb_domain_info->dns_domain,
1107 pdb_domain_info->dns_forest);
1108 if (is_root) {
1109 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1112 status = add_trusted_domain(pdb_domain_info->name,
1113 pdb_domain_info->dns_domain,
1114 &pdb_domain_info->sid,
1115 LSA_TRUST_TYPE_UPLEVEL,
1116 trust_flags,
1117 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1118 SEC_CHAN_BDC,
1119 NULL,
1120 &domain);
1121 TALLOC_FREE(pdb_domain_info);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 DBG_ERR("Failed to add our own local AD "
1124 "domain to winbindd's internal list\n");
1125 return false;
1129 * We need to call this to find out if we are an RODC
1131 ok = get_trust_pw_hash(domain->name,
1132 current_nt_hash.hash,
1133 &account_name,
1134 &sec_chan_type);
1135 if (!ok) {
1137 * If get_trust_pw_hash() fails, then try and
1138 * fetch the password from the more recent of
1139 * secrets.{ldb,tdb} using the
1140 * pdb_get_trust_credentials()
1142 ok = migrate_secrets_tdb_to_ldb(domain);
1144 if (!ok) {
1145 DEBUG(0, ("Failed to migrate our own "
1146 "local AD domain join password for "
1147 "winbindd's internal use into "
1148 "secrets.tdb\n"));
1149 return false;
1151 ok = get_trust_pw_hash(domain->name,
1152 current_nt_hash.hash,
1153 &account_name,
1154 &sec_chan_type);
1155 if (!ok) {
1156 DEBUG(0, ("Failed to find our own just "
1157 "written local AD domain join "
1158 "password for winbindd's internal "
1159 "use in secrets.tdb\n"));
1160 return false;
1164 domain->secure_channel_type = sec_chan_type;
1165 if (sec_chan_type == SEC_CHAN_RODC) {
1166 domain->rodc = true;
1169 } else {
1170 uint32_t trust_flags;
1171 enum netr_SchannelType secure_channel_type;
1173 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1174 if (role != ROLE_DOMAIN_MEMBER) {
1175 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1178 if (role > ROLE_DOMAIN_MEMBER) {
1179 secure_channel_type = SEC_CHAN_BDC;
1180 } else {
1181 secure_channel_type = SEC_CHAN_LOCAL;
1184 if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
1185 /* This is IPA DC that presents itself as
1186 * an Active Directory domain controller to trusted AD
1187 * forests but in fact is a classic domain controller.
1189 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1190 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1191 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1192 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1193 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1194 status = add_trusted_domain(pdb_domain_info->name,
1195 pdb_domain_info->dns_domain,
1196 &pdb_domain_info->sid,
1197 LSA_TRUST_TYPE_UPLEVEL,
1198 trust_flags,
1199 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1200 secure_channel_type,
1201 NULL,
1202 &domain);
1203 TALLOC_FREE(pdb_domain_info);
1204 } else {
1205 status = add_trusted_domain(get_global_sam_name(),
1206 NULL,
1207 get_global_sam_sid(),
1208 LSA_TRUST_TYPE_DOWNLEVEL,
1209 trust_flags,
1210 0, /* trust_attribs */
1211 secure_channel_type,
1212 NULL,
1213 &domain);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 DBG_ERR("Failed to add local SAM to "
1217 "domain to winbindd's internal list\n");
1218 return false;
1222 if (IS_DC) {
1223 ok = add_trusted_domains_dc();
1224 if (!ok) {
1225 DBG_ERR("init_domain_list_dc failed\n");
1226 return false;
1230 if ( role == ROLE_DOMAIN_MEMBER ) {
1231 struct dom_sid our_sid;
1232 uint32_t trust_type;
1234 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1235 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1236 return False;
1239 if (lp_realm() != NULL) {
1240 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1241 } else {
1242 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1245 status = add_trusted_domain(lp_workgroup(),
1246 lp_realm(),
1247 &our_sid,
1248 trust_type,
1249 NETR_TRUST_FLAG_PRIMARY|
1250 NETR_TRUST_FLAG_OUTBOUND,
1251 0, /* trust_attribs */
1252 SEC_CHAN_WKSTA,
1253 NULL,
1254 &domain);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 DBG_ERR("Failed to add local SAM to "
1257 "domain to winbindd's internal list\n");
1258 return false;
1262 status = imessaging_register(winbind_imessaging_context(), NULL,
1263 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1264 wb_imsg_new_trusted_domain);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1267 return false;
1270 return True;
1274 * Given a domain name, return the struct winbindd domain info for it
1276 * @note Do *not* pass lp_workgroup() to this function. domain_list
1277 * may modify it's value, and free that pointer. Instead, our local
1278 * domain may be found by calling find_our_domain().
1279 * directly.
1282 * @return The domain structure for the named domain, if it is working.
1285 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1287 struct winbindd_domain *domain;
1289 /* Search through list */
1291 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1292 if (strequal(domain_name, domain->name)) {
1293 return domain;
1295 if (domain->alt_name == NULL) {
1296 continue;
1298 if (strequal(domain_name, domain->alt_name)) {
1299 return domain;
1303 /* Not found */
1305 return NULL;
1309 * Given a domain name, return the struct winbindd domain if it's a direct
1310 * outgoing trust
1312 * @return The domain structure for the named domain, if it is a direct outgoing trust
1314 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1316 struct winbindd_domain *domain = NULL;
1318 domain = find_domain_from_name_noinit(domain_name);
1319 if (domain == NULL) {
1320 return NULL;
1323 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1324 return domain;
1327 return NULL;
1330 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1332 struct winbindd_domain *domain;
1334 domain = find_domain_from_name_noinit(domain_name);
1336 if (domain == NULL)
1337 return NULL;
1339 if (!domain->initialized)
1340 init_dc_connection(domain, false);
1342 return domain;
1345 /* Given a domain sid, return the struct winbindd domain info for it */
1347 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1349 struct winbindd_domain *domain;
1351 /* Search through list */
1353 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1354 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1355 return domain;
1358 /* Not found */
1360 return NULL;
1364 * Given a domain sid, return the struct winbindd domain if it's a direct
1365 * outgoing trust
1367 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1369 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1371 struct winbindd_domain *domain = NULL;
1373 domain = find_domain_from_sid_noinit(sid);
1374 if (domain == NULL) {
1375 return NULL;
1378 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1379 return domain;
1382 return NULL;
1385 /* Given a domain sid, return the struct winbindd domain info for it */
1387 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1389 struct winbindd_domain *domain;
1391 domain = find_domain_from_sid_noinit(sid);
1393 if (domain == NULL)
1394 return NULL;
1396 if (!domain->initialized)
1397 init_dc_connection(domain, false);
1399 return domain;
1402 struct winbindd_domain *find_our_domain(void)
1404 struct winbindd_domain *domain;
1406 /* Search through list */
1408 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1409 if (domain->primary)
1410 return domain;
1413 smb_panic("Could not find our domain");
1414 return NULL;
1417 struct winbindd_domain *find_default_route_domain(void)
1419 if (!IS_DC) {
1420 return find_our_domain();
1422 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1423 return NULL;
1426 /* Find the appropriate domain to lookup a name or SID */
1428 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1430 struct dom_sid_buf buf;
1432 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
1435 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1436 * by our passdb.
1439 if ( sid_check_is_in_unix_groups(sid) ||
1440 sid_check_is_unix_groups(sid) ||
1441 sid_check_is_in_unix_users(sid) ||
1442 sid_check_is_unix_users(sid) ||
1443 sid_check_is_our_sam(sid) ||
1444 sid_check_is_in_our_sam(sid) )
1446 return find_domain_from_sid(get_global_sam_sid());
1449 if ( sid_check_is_builtin(sid) ||
1450 sid_check_is_in_builtin(sid) ||
1451 sid_check_is_wellknown_domain(sid, NULL) ||
1452 sid_check_is_in_wellknown_domain(sid) )
1454 return find_domain_from_sid(&global_sid_Builtin);
1457 if (IS_DC) {
1458 struct winbindd_domain *domain = NULL;
1460 domain = find_domain_from_sid_noinit(sid);
1461 if (domain == NULL) {
1462 return NULL;
1465 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1466 return domain;
1469 return domain->routing_domain;
1472 /* On a member server a query for SID or name can always go to our
1473 * primary DC. */
1475 DEBUG(10, ("calling find_our_domain\n"));
1476 return find_our_domain();
1479 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1481 bool predefined;
1483 if ( strequal(domain_name, unix_users_domain_name() ) ||
1484 strequal(domain_name, unix_groups_domain_name() ) )
1487 * The "Unix User" and "Unix Group" domain are handled by
1488 * passdb
1490 return find_domain_from_name_noinit( get_global_sam_name() );
1493 if (strequal(domain_name, "BUILTIN") ||
1494 strequal(domain_name, get_global_sam_name())) {
1495 return find_domain_from_name_noinit(domain_name);
1498 predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1499 if (predefined) {
1500 return find_domain_from_name_noinit(builtin_domain_name());
1503 if (IS_DC) {
1504 struct winbindd_domain *domain = NULL;
1506 domain = find_domain_from_name_noinit(domain_name);
1507 if (domain == NULL) {
1508 return NULL;
1511 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1512 return domain;
1515 return domain->routing_domain;
1518 return find_our_domain();
1521 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1523 static bool assume_domain(const char *domain)
1525 /* never assume the domain on a standalone server */
1527 if ( lp_server_role() == ROLE_STANDALONE )
1528 return False;
1530 /* domain member servers may possibly assume for the domain name */
1532 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1533 if ( !strequal(lp_workgroup(), domain) )
1534 return False;
1536 if ( lp_winbind_use_default_domain() )
1537 return True;
1540 /* only left with a domain controller */
1542 if ( strequal(get_global_sam_name(), domain) ) {
1543 return True;
1546 return False;
1549 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1550 bool parse_domain_user(TALLOC_CTX *ctx,
1551 const char *domuser,
1552 char **pnamespace,
1553 char **pdomain,
1554 char **puser)
1556 char *p = NULL;
1557 char *namespace = NULL;
1558 char *domain = NULL;
1559 char *user = NULL;
1561 if (strlen(domuser) == 0) {
1562 return false;
1565 p = strchr(domuser, *lp_winbind_separator());
1566 if (p != NULL) {
1567 user = talloc_strdup(ctx, p + 1);
1568 if (user == NULL) {
1569 goto fail;
1571 domain = talloc_strdup(ctx,
1572 domuser);
1573 if (domain == NULL) {
1574 goto fail;
1576 domain[PTR_DIFF(p, domuser)] = '\0';
1577 namespace = talloc_strdup(ctx, domain);
1578 if (namespace == NULL) {
1579 goto fail;
1581 } else {
1582 user = talloc_strdup(ctx, domuser);
1583 if (user == NULL) {
1584 goto fail;
1586 p = strchr(domuser, '@');
1587 if (p != NULL) {
1588 /* upn */
1589 namespace = talloc_strdup(ctx, p + 1);
1590 if (namespace == NULL) {
1591 goto fail;
1593 domain = talloc_strdup(ctx, "");
1594 if (domain == NULL) {
1595 goto fail;
1598 } else if (assume_domain(lp_workgroup())) {
1599 domain = talloc_strdup(ctx, lp_workgroup());
1600 if (domain == NULL) {
1601 goto fail;
1603 namespace = talloc_strdup(ctx, domain);
1604 if (namespace == NULL) {
1605 goto fail;
1607 } else {
1608 namespace = talloc_strdup(ctx, lp_netbios_name());
1609 if (namespace == NULL) {
1610 goto fail;
1612 domain = talloc_strdup(ctx, "");
1613 if (domain == NULL) {
1614 goto fail;
1619 if (!strupper_m(domain)) {
1620 goto fail;
1623 *pnamespace = namespace;
1624 *pdomain = domain;
1625 *puser = user;
1626 return true;
1627 fail:
1628 TALLOC_FREE(user);
1629 TALLOC_FREE(domain);
1630 TALLOC_FREE(namespace);
1631 return false;
1634 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1635 bool parse_domain_user_fstr(const char *domuser,
1636 fstring namespace,
1637 fstring domain,
1638 fstring user)
1640 char *p = NULL;
1642 if (strlen(domuser) == 0) {
1643 return false;
1646 p = strchr(domuser, *lp_winbind_separator());
1647 if (p != NULL) {
1648 if (PTR_DIFF(p, domuser) >= sizeof(fstring)) {
1649 DBG_ERR("index %td exceeds len of dest string %zu\n",
1650 PTR_DIFF(p, domuser),
1651 (sizeof(fstring) - 1));
1652 return false;
1654 fstrcpy(user, p + 1);
1655 fstrcpy(domain, domuser);
1656 domain[PTR_DIFF(p, domuser)] = '\0';
1657 fstrcpy(namespace, domain);
1658 } else {
1659 fstrcpy(user, domuser);
1661 domain[0] = '\0';
1662 namespace[0] = '\0';
1663 p = strchr(domuser, '@');
1664 if (p != NULL) {
1665 /* upn */
1666 fstrcpy(namespace, p + 1);
1667 } else if (assume_domain(lp_workgroup())) {
1668 fstrcpy(domain, lp_workgroup());
1669 fstrcpy(namespace, domain);
1670 } else {
1671 fstrcpy(namespace, lp_netbios_name());
1675 return strupper_m(domain);
1678 bool canonicalize_username(TALLOC_CTX *mem_ctx,
1679 char **pusername_inout,
1680 char **pnamespace,
1681 char **pdomain,
1682 char **puser)
1684 bool ok;
1685 char *namespace = NULL;
1686 char *domain = NULL;
1687 char *user = NULL;
1688 char *username_inout = NULL;
1690 ok = parse_domain_user(mem_ctx,
1691 *pusername_inout,
1692 &namespace, &domain, &user);
1694 if (!ok) {
1695 return False;
1698 username_inout = talloc_asprintf(mem_ctx, "%s%c%s",
1699 domain, *lp_winbind_separator(),
1700 user);
1702 if (username_inout == NULL) {
1703 goto fail;
1706 *pnamespace = namespace;
1707 *puser = user;
1708 *pdomain = domain;
1709 *pusername_inout = username_inout;
1710 return True;
1711 fail:
1712 TALLOC_FREE(username_inout);
1713 TALLOC_FREE(namespace);
1714 TALLOC_FREE(domain);
1715 TALLOC_FREE(user);
1716 return false;
1720 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1721 'winbind separator' options.
1722 This means:
1723 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1724 lp_workgroup()
1726 If we are a PDC or BDC, and this is for our domain, do likewise.
1728 On an AD DC we always fill DOMAIN\\USERNAME.
1730 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1733 * talloc version of fill_domain_username()
1734 * return NULL on talloc failure.
1736 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1737 const char *domain,
1738 const char *user,
1739 bool can_assume)
1741 char *tmp_user, *name;
1743 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1744 can_assume = false;
1747 if (user == NULL) {
1748 return NULL;
1751 tmp_user = talloc_strdup(mem_ctx, user);
1752 if (tmp_user == NULL) {
1753 return NULL;
1755 if (!strlower_m(tmp_user)) {
1756 TALLOC_FREE(tmp_user);
1757 return NULL;
1760 if (can_assume && assume_domain(domain)) {
1761 name = tmp_user;
1762 } else {
1763 name = talloc_asprintf(mem_ctx, "%s%c%s",
1764 domain,
1765 *lp_winbind_separator(),
1766 tmp_user);
1767 TALLOC_FREE(tmp_user);
1770 return name;
1774 * Client list accessor functions
1777 static struct winbindd_cli_state *_client_list;
1778 static int _num_clients;
1780 /* Return list of all connected clients */
1782 struct winbindd_cli_state *winbindd_client_list(void)
1784 return _client_list;
1787 /* Return list-tail of all connected clients */
1789 struct winbindd_cli_state *winbindd_client_list_tail(void)
1791 return DLIST_TAIL(_client_list);
1794 /* Return previous (read:newer) client in list */
1796 struct winbindd_cli_state *
1797 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1799 return DLIST_PREV(cli);
1802 /* Add a connection to the list */
1804 void winbindd_add_client(struct winbindd_cli_state *cli)
1806 cli->last_access = time(NULL);
1807 DLIST_ADD(_client_list, cli);
1808 _num_clients++;
1811 /* Remove a client from the list */
1813 void winbindd_remove_client(struct winbindd_cli_state *cli)
1815 DLIST_REMOVE(_client_list, cli);
1816 _num_clients--;
1819 /* Move a client to head or list */
1821 void winbindd_promote_client(struct winbindd_cli_state *cli)
1823 cli->last_access = time(NULL);
1824 DLIST_PROMOTE(_client_list, cli);
1827 /* Return number of open clients */
1829 int winbindd_num_clients(void)
1831 return _num_clients;
1834 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1835 const struct dom_sid *user_sid,
1836 uint32_t *p_num_groups, struct dom_sid **user_sids)
1838 struct netr_SamInfo3 *info3 = NULL;
1839 NTSTATUS status = NT_STATUS_NO_MEMORY;
1840 uint32_t num_groups = 0;
1842 DEBUG(3,(": lookup_usergroups_cached\n"));
1844 *user_sids = NULL;
1845 *p_num_groups = 0;
1847 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1849 if (info3 == NULL) {
1850 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1854 * Before bug #7843 the "Domain Local" groups were added with a
1855 * lookupuseraliases call, but this isn't done anymore for our domain
1856 * so we need to resolve resource groups here.
1858 * When to use Resource Groups:
1859 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1861 status = sid_array_from_info3(mem_ctx, info3,
1862 user_sids,
1863 &num_groups,
1864 false);
1866 if (!NT_STATUS_IS_OK(status)) {
1867 TALLOC_FREE(info3);
1868 return status;
1871 TALLOC_FREE(info3);
1872 *p_num_groups = num_groups;
1873 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1875 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1877 return status;
1880 /*********************************************************************
1881 We use this to remove spaces from user and group names
1882 ********************************************************************/
1884 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1885 const char *domain_name,
1886 const char *name,
1887 char **normalized)
1889 struct winbindd_domain *domain = NULL;
1890 NTSTATUS nt_status;
1892 if (!name || !normalized) {
1893 return NT_STATUS_INVALID_PARAMETER;
1896 if (!lp_winbind_normalize_names()) {
1897 return NT_STATUS_PROCEDURE_NOT_FOUND;
1900 domain = find_domain_from_name_noinit(domain_name);
1901 if (domain == NULL) {
1902 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1903 return NT_STATUS_NO_SUCH_DOMAIN;
1906 /* Alias support and whitespace replacement are mutually
1907 exclusive */
1909 nt_status = resolve_username_to_alias(mem_ctx, domain,
1910 name, normalized );
1911 if (NT_STATUS_IS_OK(nt_status)) {
1912 /* special return code to let the caller know we
1913 mapped to an alias */
1914 return NT_STATUS_FILE_RENAMED;
1917 /* check for an unreachable domain */
1919 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1920 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1921 domain->name));
1922 set_domain_offline(domain);
1923 return nt_status;
1926 /* deal with whitespace */
1928 *normalized = talloc_strdup(mem_ctx, name);
1929 if (!(*normalized)) {
1930 return NT_STATUS_NO_MEMORY;
1933 all_string_sub( *normalized, " ", "_", 0 );
1935 return NT_STATUS_OK;
1938 /*********************************************************************
1939 We use this to do the inverse of normalize_name_map()
1940 ********************************************************************/
1942 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1943 const char *name,
1944 char **normalized)
1946 NTSTATUS nt_status;
1947 struct winbindd_domain *domain = find_our_domain();
1949 if (!name || !normalized) {
1950 return NT_STATUS_INVALID_PARAMETER;
1953 if (!lp_winbind_normalize_names()) {
1954 return NT_STATUS_PROCEDURE_NOT_FOUND;
1957 /* Alias support and whitespace replacement are mutally
1958 exclusive */
1960 /* When mapping from an alias to a username, we don't know the
1961 domain. But we only need a domain structure to cache
1962 a successful lookup , so just our own domain structure for
1963 the seqnum. */
1965 nt_status = resolve_alias_to_username(mem_ctx, domain,
1966 name, normalized);
1967 if (NT_STATUS_IS_OK(nt_status)) {
1968 /* Special return code to let the caller know we mapped
1969 from an alias */
1970 return NT_STATUS_FILE_RENAMED;
1973 /* check for an unreachable domain */
1975 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1976 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1977 domain->name));
1978 set_domain_offline(domain);
1979 return nt_status;
1982 /* deal with whitespace */
1984 *normalized = talloc_strdup(mem_ctx, name);
1985 if (!(*normalized)) {
1986 return NT_STATUS_NO_MEMORY;
1989 all_string_sub(*normalized, "_", " ", 0);
1991 return NT_STATUS_OK;
1994 /*********************************************************************
1995 ********************************************************************/
1997 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1999 struct winbindd_tdc_domain *tdc = NULL;
2000 TALLOC_CTX *frame = talloc_stackframe();
2001 bool ret = false;
2003 /* We can contact the domain if it is our primary domain */
2005 if (domain->primary) {
2006 ret = true;
2007 goto done;
2010 /* Trust the TDC cache and not the winbindd_domain flags */
2012 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
2013 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
2014 domain->name));
2015 ret = false;
2016 goto done;
2019 /* Can always contact a domain that is in out forest */
2021 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2022 ret = true;
2023 goto done;
2027 * On a _member_ server, we cannot contact the domain if it
2028 * is running AD and we have no inbound trust.
2031 if (!IS_DC &&
2032 domain->active_directory &&
2033 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
2035 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
2036 "and we have no inbound trust.\n", domain->name));
2037 goto done;
2040 /* Assume everything else is ok (probably not true but what
2041 can you do?) */
2043 ret = true;
2045 done:
2046 talloc_destroy(frame);
2048 return ret;
2051 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
2053 /*********************************************************************
2054 ********************************************************************/
2056 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
2058 char *var = NULL;
2059 char addr[INET6_ADDRSTRLEN];
2060 const char *kdc = NULL;
2061 int lvl = 11;
2063 if (!domain || !domain->alt_name || !*domain->alt_name) {
2064 return;
2067 if (domain->initialized && !domain->active_directory) {
2068 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2069 domain->alt_name));
2070 return;
2073 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2074 kdc = addr;
2075 if (!*kdc) {
2076 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2077 domain->alt_name));
2078 kdc = domain->dcname;
2081 if (!kdc || !*kdc) {
2082 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2083 domain->alt_name));
2084 return;
2087 var = talloc_asprintf_strupper_m(
2088 talloc_tos(),
2089 "%s_%s",
2090 WINBINDD_LOCATOR_KDC_ADDRESS,
2091 domain->alt_name);
2092 if (var == NULL) {
2093 return;
2096 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2097 var, kdc));
2099 setenv(var, kdc, 1);
2100 TALLOC_FREE(var);
2103 /*********************************************************************
2104 ********************************************************************/
2106 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2108 struct winbindd_domain *our_dom = find_our_domain();
2110 winbindd_set_locator_kdc_env(domain);
2112 if (domain != our_dom) {
2113 winbindd_set_locator_kdc_env(our_dom);
2117 /*********************************************************************
2118 ********************************************************************/
2120 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2122 char *var = NULL;
2124 if (!domain || !domain->alt_name || !*domain->alt_name) {
2125 return;
2128 var = talloc_asprintf_strupper_m(
2129 talloc_tos(),
2130 "%s_%s",
2131 WINBINDD_LOCATOR_KDC_ADDRESS,
2132 domain->alt_name);
2133 if (var == NULL) {
2134 return;
2137 unsetenv(var);
2138 TALLOC_FREE(var);
2140 #else
2142 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2144 return;
2147 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2149 return;
2152 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2154 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2157 * Make sure we start with authoritative=true,
2158 * it will only set to false if we don't know the
2159 * domain.
2161 resp->data.auth.authoritative = true;
2163 resp->data.auth.nt_status = NT_STATUS_V(result);
2164 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2166 /* we might have given a more useful error above */
2167 if (*resp->data.auth.error_string == '\0')
2168 fstrcpy(resp->data.auth.error_string,
2169 get_friendly_nt_error_msg(result));
2170 resp->data.auth.pam_error = nt_status_to_pam(result);
2173 bool is_domain_offline(const struct winbindd_domain *domain)
2175 if (get_global_winbindd_state_offline()) {
2176 return true;
2178 return !domain->online;
2181 bool is_domain_online(const struct winbindd_domain *domain)
2183 return !is_domain_offline(domain);
2187 * Parse an char array into a list of sids.
2189 * The input sidstr should consist of 0-terminated strings
2190 * representing sids, separated by newline characters '\n'.
2191 * The list is terminated by an empty string, i.e.
2192 * character '\0' directly following a character '\n'
2193 * (or '\0' right at the start of sidstr).
2195 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2196 struct dom_sid **sids, uint32_t *num_sids)
2198 const char *p;
2200 p = sidstr;
2201 if (p == NULL)
2202 return False;
2204 while (p[0] != '\0') {
2205 struct dom_sid sid;
2206 const char *q = NULL;
2208 if (!dom_sid_parse_endp(p, &sid, &q)) {
2209 DEBUG(1, ("Could not parse sid %s\n", p));
2210 return false;
2212 if (q[0] != '\n') {
2213 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2214 return false;
2216 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2217 num_sids)))
2219 return False;
2221 p = q+1;
2223 return True;
2226 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2227 struct unixid **pxids, uint32_t *pnum_xids)
2229 const char *p;
2230 struct unixid *xids = NULL;
2231 uint32_t num_xids = 0;
2233 p = xidstr;
2234 if (p == NULL) {
2235 return false;
2238 while (p[0] != '\0') {
2239 struct unixid *tmp;
2240 struct unixid xid;
2241 unsigned long long id;
2242 char *endp;
2243 int error = 0;
2245 switch (p[0]) {
2246 case 'U':
2247 xid = (struct unixid) { .type = ID_TYPE_UID };
2248 break;
2249 case 'G':
2250 xid = (struct unixid) { .type = ID_TYPE_GID };
2251 break;
2252 default:
2253 return false;
2256 p += 1;
2258 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2259 if (error != 0) {
2260 goto fail;
2262 if (*endp != '\n') {
2263 goto fail;
2265 p = endp+1;
2267 xid.id = id;
2268 if ((unsigned long long)xid.id != id) {
2269 goto fail;
2272 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2273 if (tmp == NULL) {
2274 return 0;
2276 xids = tmp;
2278 xids[num_xids] = xid;
2279 num_xids += 1;
2282 *pxids = xids;
2283 *pnum_xids = num_xids;
2284 return true;
2286 fail:
2287 TALLOC_FREE(xids);
2288 return false;