test3: Fix usage check for test_sharesec.sh
[Samba.git] / source3 / winbindd / winbindd_util.c
blobc2f02b74211e8b976d8405f45494e7a36c954881
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"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_WINBIND
40 /**
41 * @file winbindd_util.c
43 * Winbind daemon for NT domain authentication nss module.
44 **/
46 static bool add_trusted_domains_dc(void);
48 /* The list of trusted domains. Note that the list can be deleted and
49 recreated using the init_domain_list() function so pointers to
50 individual winbindd_domain structures cannot be made. Keep a copy of
51 the domain name instead. */
53 static struct winbindd_domain *_domain_list = NULL;
55 struct winbindd_domain *domain_list(void)
57 /* Initialise list */
59 if ((!_domain_list) && (!init_domain_list())) {
60 smb_panic("Init_domain_list failed");
63 return _domain_list;
66 /* Free all entries in the trusted domain list */
68 static void free_domain_list(void)
70 struct winbindd_domain *domain = _domain_list;
72 while(domain) {
73 struct winbindd_domain *next = domain->next;
75 DLIST_REMOVE(_domain_list, domain);
76 TALLOC_FREE(domain);
77 domain = next;
81 /**
82 * Iterator for winbindd's domain list.
83 * To be used (e.g.) in tevent based loops.
85 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
87 if (domain == NULL) {
88 domain = domain_list();
89 } else {
90 domain = domain->next;
93 if ((domain != NULL) &&
94 (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
95 sid_check_is_our_sam(&domain->sid))
97 domain = domain->next;
100 return domain;
103 static bool is_internal_domain(const struct dom_sid *sid)
105 if (sid == NULL)
106 return False;
108 return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
111 /* Add a trusted domain to our list of domains.
112 If the domain already exists in the list,
113 return it and don't re-initialize. */
115 static NTSTATUS add_trusted_domain(const char *domain_name,
116 const char *dns_name,
117 const struct dom_sid *sid,
118 uint32_t trust_type,
119 uint32_t trust_flags,
120 uint32_t trust_attribs,
121 enum netr_SchannelType secure_channel_type,
122 struct winbindd_domain *routing_domain,
123 struct winbindd_domain **_d)
125 struct winbindd_domain *domain = NULL;
126 const char **ignored_domains = NULL;
127 const char **dom = 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 ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
137 for (dom=ignored_domains; dom && *dom; dom++) {
138 if (gen_fnmatch(*dom, domain_name) == 0) {
139 DEBUG(2,("Ignoring domain '%s'\n", domain_name));
140 return NT_STATUS_NO_SUCH_DOMAIN;
145 * We can't call domain_list() as this function is called from
146 * init_domain_list() and we'll get stuck in a loop.
148 for (domain = _domain_list; domain; domain = domain->next) {
149 if (strequal(domain_name, domain->name)) {
150 break;
154 if (domain != NULL) {
155 struct winbindd_domain *check_domain = NULL;
157 for (check_domain = _domain_list;
158 check_domain != NULL;
159 check_domain = check_domain->next)
161 if (check_domain == domain) {
162 continue;
165 if (dom_sid_equal(&check_domain->sid, sid)) {
166 break;
170 if (check_domain != NULL) {
171 DBG_ERR("SID [%s] already used by domain [%s], "
172 "expected [%s]\n",
173 dom_sid_str_buf(sid, &buf),
174 check_domain->name,
175 domain->name);
176 return NT_STATUS_INVALID_PARAMETER;
180 if ((domain != NULL) && (dns_name != NULL)) {
181 struct winbindd_domain *check_domain = NULL;
183 for (check_domain = _domain_list;
184 check_domain != NULL;
185 check_domain = check_domain->next)
187 if (check_domain == domain) {
188 continue;
191 if (strequal(check_domain->alt_name, dns_name)) {
192 break;
196 if (check_domain != NULL) {
197 DBG_ERR("DNS name [%s] used by domain [%s], "
198 "expected [%s]\n",
199 dns_name, check_domain->name,
200 domain->name);
201 return NT_STATUS_INVALID_PARAMETER;
205 if (domain != NULL) {
206 *_d = domain;
207 return NT_STATUS_OK;
210 /* Create new domain entry */
211 domain = talloc_zero(NULL, struct winbindd_domain);
212 if (domain == NULL) {
213 return NT_STATUS_NO_MEMORY;
216 domain->children = talloc_zero_array(domain,
217 struct winbindd_child,
218 lp_winbind_max_domain_connections());
219 if (domain->children == NULL) {
220 TALLOC_FREE(domain);
221 return NT_STATUS_NO_MEMORY;
224 domain->queue = tevent_queue_create(domain, "winbind_domain");
225 if (domain->queue == NULL) {
226 TALLOC_FREE(domain);
227 return NT_STATUS_NO_MEMORY;
230 domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
231 if (domain->binding_handle == NULL) {
232 TALLOC_FREE(domain);
233 return NT_STATUS_NO_MEMORY;
236 domain->name = talloc_strdup(domain, domain_name);
237 if (domain->name == NULL) {
238 TALLOC_FREE(domain);
239 return NT_STATUS_NO_MEMORY;
242 if (dns_name != NULL) {
243 domain->alt_name = talloc_strdup(domain, dns_name);
244 if (domain->alt_name == NULL) {
245 TALLOC_FREE(domain);
246 return NT_STATUS_NO_MEMORY;
250 domain->backend = NULL;
251 domain->internal = is_internal_domain(sid);
252 domain->secure_channel_type = secure_channel_type;
253 domain->sequence_number = DOM_SEQUENCE_NONE;
254 domain->last_seq_check = 0;
255 domain->initialized = false;
256 domain->online = is_internal_domain(sid);
257 domain->check_online_timeout = 0;
258 domain->dc_probe_pid = (pid_t)-1;
259 domain->domain_flags = trust_flags;
260 domain->domain_type = trust_type;
261 domain->domain_trust_attribs = trust_attribs;
262 domain->secure_channel_type = secure_channel_type;
263 domain->routing_domain = routing_domain;
264 sid_copy(&domain->sid, sid);
266 /* Is this our primary domain ? */
267 if (role == ROLE_DOMAIN_MEMBER) {
268 domain->primary = strequal(domain_name, lp_workgroup());
269 } else {
270 domain->primary = strequal(domain_name, get_global_sam_name());
273 if (domain->primary) {
274 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
275 domain->active_directory = true;
277 if (lp_security() == SEC_ADS) {
278 domain->active_directory = true;
280 } else if (!domain->internal) {
281 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
282 domain->active_directory = true;
286 domain->can_do_ncacn_ip_tcp = domain->active_directory;
288 /* Link to domain list */
289 DLIST_ADD_END(_domain_list, domain);
291 wcache_tdc_add_domain( domain );
293 setup_domain_child(domain);
295 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
296 domain->name, domain->alt_name,
297 dom_sid_str_buf(&domain->sid, &buf));
299 *_d = domain;
300 return NT_STATUS_OK;
303 bool set_routing_domain(struct winbindd_domain *domain,
304 struct winbindd_domain *routing_domain)
306 if (domain->routing_domain == NULL) {
307 domain->routing_domain = routing_domain;
308 return true;
310 if (domain->routing_domain != routing_domain) {
311 return false;
313 return true;
316 bool add_trusted_domain_from_auth(uint16_t validation_level,
317 struct info3_text *info3,
318 struct info6_text *info6)
320 struct winbindd_domain *domain = NULL;
321 struct dom_sid domain_sid;
322 const char *dns_domainname = NULL;
323 NTSTATUS status;
324 bool ok;
327 * We got a successfull auth from a domain that might not yet be in our
328 * domain list. If we're a member we trust our DC who authenticated the
329 * user from that domain and add the domain to our list on-the-fly. If
330 * we're a DC we rely on configured trusts and don't add on-the-fly.
333 if (IS_DC) {
334 return true;
337 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
338 if (!ok) {
339 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
340 return false;
343 if (validation_level == 6) {
344 if (!strequal(info6->dns_domainname, "")) {
345 dns_domainname = info6->dns_domainname;
349 status = add_trusted_domain(info3->logon_dom,
350 dns_domainname,
351 &domain_sid,
353 NETR_TRUST_FLAG_OUTBOUND,
355 SEC_CHAN_NULL,
356 find_default_route_domain(),
357 &domain);
358 if (!NT_STATUS_IS_OK(status) &&
359 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
361 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
362 info3->logon_dom, info3->dom_sid);
363 return false;
366 return true;
369 bool domain_is_forest_root(const struct winbindd_domain *domain)
371 const uint32_t fr_flags =
372 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
374 return ((domain->domain_flags & fr_flags) == fr_flags);
377 /********************************************************************
378 rescan our domains looking for new trusted domains
379 ********************************************************************/
381 struct trustdom_state {
382 struct winbindd_domain *domain;
383 struct winbindd_request request;
386 static void trustdom_list_done(struct tevent_req *req);
387 static void rescan_forest_root_trusts( void );
388 static void rescan_forest_trusts( void );
390 static void add_trusted_domains( struct winbindd_domain *domain )
392 struct trustdom_state *state;
393 struct tevent_req *req;
395 state = talloc_zero(NULL, struct trustdom_state);
396 if (state == NULL) {
397 DEBUG(0, ("talloc failed\n"));
398 return;
400 state->domain = domain;
402 state->request.length = sizeof(state->request);
403 state->request.cmd = WINBINDD_LIST_TRUSTDOM;
405 req = wb_domain_request_send(state, global_event_context(),
406 domain, &state->request);
407 if (req == NULL) {
408 DEBUG(1, ("wb_domain_request_send failed\n"));
409 TALLOC_FREE(state);
410 return;
412 tevent_req_set_callback(req, trustdom_list_done, state);
415 static void trustdom_list_done(struct tevent_req *req)
417 struct trustdom_state *state = tevent_req_callback_data(
418 req, struct trustdom_state);
419 struct winbindd_response *response;
420 int res, err;
421 char *p;
422 ptrdiff_t extra_len;
423 bool within_forest = false;
424 NTSTATUS status;
427 * Only when we enumerate our primary domain
428 * or our forest root domain, we should keep
429 * the NETR_TRUST_FLAG_IN_FOREST flag, in
430 * all other cases we need to clear it as the domain
431 * is not part of our forest.
433 if (state->domain->primary) {
434 within_forest = true;
435 } else if (domain_is_forest_root(state->domain)) {
436 within_forest = true;
439 res = wb_domain_request_recv(req, state, &response, &err);
440 if ((res == -1) || (response->result != WINBINDD_OK)) {
441 DBG_WARNING("Could not receive trusts for domain %s\n",
442 state->domain->name);
443 TALLOC_FREE(state);
444 return;
447 if (response->length < sizeof(struct winbindd_response)) {
448 DBG_ERR("ill-formed trustdom response - short length\n");
449 TALLOC_FREE(state);
450 return;
453 extra_len = response->length - sizeof(struct winbindd_response);
455 p = (char *)response->extra_data.data;
457 while ((p - (char *)response->extra_data.data) < extra_len) {
458 struct winbindd_domain *domain = NULL;
459 char *name, *q, *sidstr, *alt_name;
460 struct dom_sid sid;
461 uint32_t trust_type;
462 uint32_t trust_attribs;
463 uint32_t trust_flags;
464 int error = 0;
466 DBG_DEBUG("parsing response line '%s'\n", p);
468 name = p;
470 alt_name = strchr(p, '\\');
471 if (alt_name == NULL) {
472 DBG_ERR("Got invalid trustdom response\n");
473 break;
476 *alt_name = '\0';
477 alt_name += 1;
479 sidstr = strchr(alt_name, '\\');
480 if (sidstr == NULL) {
481 DBG_ERR("Got invalid trustdom response\n");
482 break;
485 *sidstr = '\0';
486 sidstr += 1;
488 /* use the real alt_name if we have one, else pass in NULL */
489 if (strequal(alt_name, "(null)")) {
490 alt_name = NULL;
493 q = strtok(sidstr, "\\");
494 if (q == NULL) {
495 DBG_ERR("Got invalid trustdom response\n");
496 break;
499 if (!string_to_sid(&sid, sidstr)) {
500 DEBUG(0, ("Got invalid trustdom response\n"));
501 break;
504 q = strtok(NULL, "\\");
505 if (q == NULL) {
506 DBG_ERR("Got invalid trustdom response\n");
507 break;
510 trust_flags = (uint32_t)smb_strtoul(q,
511 NULL,
513 &error,
514 SMB_STR_STANDARD);
515 if (error != 0) {
516 DBG_ERR("Failed to convert trust_flags\n");
517 break;
520 q = strtok(NULL, "\\");
521 if (q == NULL) {
522 DBG_ERR("Got invalid trustdom response\n");
523 break;
526 trust_type = (uint32_t)smb_strtoul(q,
527 NULL,
529 &error,
530 SMB_STR_STANDARD);
531 if (error != 0) {
532 DBG_ERR("Failed to convert trust_type\n");
533 break;
536 q = strtok(NULL, "\n");
537 if (q == NULL) {
538 DBG_ERR("Got invalid trustdom response\n");
539 break;
542 trust_attribs = (uint32_t)smb_strtoul(q,
543 NULL,
545 &error,
546 SMB_STR_STANDARD);
547 if (error != 0) {
548 DBG_ERR("Failed to convert trust_attribs\n");
549 break;
552 if (!within_forest) {
553 trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
556 if (!state->domain->primary) {
557 trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
561 * We always call add_trusted_domain() cause on an existing
562 * domain structure, it will update the SID if necessary.
563 * This is important because we need the SID for sibling
564 * domains.
566 status = add_trusted_domain(name,
567 alt_name,
568 &sid,
569 trust_type,
570 trust_flags,
571 trust_attribs,
572 SEC_CHAN_NULL,
573 find_default_route_domain(),
574 &domain);
575 if (!NT_STATUS_IS_OK(status) &&
576 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
578 DBG_NOTICE("add_trusted_domain returned %s\n",
579 nt_errstr(status));
580 return;
583 p = q + strlen(q) + 1;
587 Cases to consider when scanning trusts:
588 (a) we are calling from a child domain (primary && !forest_root)
589 (b) we are calling from the root of the forest (primary && forest_root)
590 (c) we are calling from a trusted forest domain (!primary
591 && !forest_root)
594 if (state->domain->primary) {
595 /* If this is our primary domain and we are not in the
596 forest root, we have to scan the root trusts first */
598 if (!domain_is_forest_root(state->domain))
599 rescan_forest_root_trusts();
600 else
601 rescan_forest_trusts();
603 } else if (domain_is_forest_root(state->domain)) {
604 /* Once we have done root forest trust search, we can
605 go on to search the trusted forests */
607 rescan_forest_trusts();
610 TALLOC_FREE(state);
612 return;
615 /********************************************************************
616 Scan the trusts of our forest root
617 ********************************************************************/
619 static void rescan_forest_root_trusts( void )
621 struct winbindd_tdc_domain *dom_list = NULL;
622 size_t num_trusts = 0;
623 size_t i;
624 NTSTATUS status;
626 /* The only transitive trusts supported by Windows 2003 AD are
627 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
628 first two are handled in forest and listed by
629 DsEnumerateDomainTrusts(). Forest trusts are not so we
630 have to do that ourselves. */
632 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
633 return;
635 for ( i=0; i<num_trusts; i++ ) {
636 struct winbindd_domain *d = NULL;
638 /* Find the forest root. Don't necessarily trust
639 the domain_list() as our primary domain may not
640 have been initialized. */
642 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
643 continue;
646 /* Here's the forest root */
648 d = find_domain_from_name_noinit( dom_list[i].domain_name );
649 if (d == NULL) {
650 status = add_trusted_domain(dom_list[i].domain_name,
651 dom_list[i].dns_name,
652 &dom_list[i].sid,
653 dom_list[i].trust_type,
654 dom_list[i].trust_flags,
655 dom_list[i].trust_attribs,
656 SEC_CHAN_NULL,
657 find_default_route_domain(),
658 &d);
660 if (!NT_STATUS_IS_OK(status) &&
661 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
663 DBG_ERR("add_trusted_domain returned %s\n",
664 nt_errstr(status));
665 return;
668 if (d == NULL) {
669 continue;
672 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
673 "for domain tree root %s (%s)\n",
674 d->name, d->alt_name ));
676 d->domain_flags = dom_list[i].trust_flags;
677 d->domain_type = dom_list[i].trust_type;
678 d->domain_trust_attribs = dom_list[i].trust_attribs;
680 add_trusted_domains( d );
682 break;
685 TALLOC_FREE( dom_list );
687 return;
690 /********************************************************************
691 scan the transitive forest trusts (not our own)
692 ********************************************************************/
695 static void rescan_forest_trusts( void )
697 struct winbindd_domain *d = NULL;
698 struct winbindd_tdc_domain *dom_list = NULL;
699 size_t num_trusts = 0;
700 size_t i;
701 NTSTATUS status;
703 /* The only transitive trusts supported by Windows 2003 AD are
704 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
705 first two are handled in forest and listed by
706 DsEnumerateDomainTrusts(). Forest trusts are not so we
707 have to do that ourselves. */
709 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
710 return;
712 for ( i=0; i<num_trusts; i++ ) {
713 uint32_t flags = dom_list[i].trust_flags;
714 uint32_t type = dom_list[i].trust_type;
715 uint32_t attribs = dom_list[i].trust_attribs;
717 d = find_domain_from_name_noinit( dom_list[i].domain_name );
719 /* ignore our primary and internal domains */
721 if ( d && (d->internal || d->primary ) )
722 continue;
724 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
725 (type == LSA_TRUST_TYPE_UPLEVEL) &&
726 (attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
728 /* add the trusted domain if we don't know
729 about it */
731 if (d == NULL) {
732 status = add_trusted_domain(
733 dom_list[i].domain_name,
734 dom_list[i].dns_name,
735 &dom_list[i].sid,
736 type,
737 flags,
738 attribs,
739 SEC_CHAN_NULL,
740 find_default_route_domain(),
741 &d);
742 if (!NT_STATUS_IS_OK(status) &&
743 NT_STATUS_EQUAL(status,
744 NT_STATUS_NO_SUCH_DOMAIN))
746 DBG_ERR("add_trusted_domain: %s\n",
747 nt_errstr(status));
748 return;
752 if (d == NULL) {
753 continue;
756 DEBUG(10,("Following trust path for domain %s (%s)\n",
757 d->name, d->alt_name ));
758 add_trusted_domains( d );
762 TALLOC_FREE( dom_list );
764 return;
767 /*********************************************************************
768 The process of updating the trusted domain list is a three step
769 async process:
770 (a) ask our domain
771 (b) ask the root domain in our forest
772 (c) ask the a DC in any Win2003 trusted forests
773 *********************************************************************/
775 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
776 struct timeval now, void *private_data)
778 TALLOC_FREE(te);
780 /* I use to clear the cache here and start over but that
781 caused problems in child processes that needed the
782 trust dom list early on. Removing it means we
783 could have some trusted domains listed that have been
784 removed from our primary domain's DC until a full
785 restart. This should be ok since I think this is what
786 Windows does as well. */
788 /* this will only add new domains we didn't already know about
789 in the domain_list()*/
791 add_trusted_domains( find_our_domain() );
793 te = tevent_add_timer(
794 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
795 rescan_trusted_domains, NULL);
797 * If te == NULL, there's not much we can do here. Don't fail, the
798 * only thing we miss is new trusted domains.
801 return;
804 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
805 struct winbindd_cli_state *state)
807 /* Ensure null termination */
808 state->request->domain_name
809 [sizeof(state->request->domain_name)-1]='\0';
810 state->request->data.init_conn.dcname
811 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
813 if (strlen(state->request->data.init_conn.dcname) > 0) {
814 TALLOC_FREE(domain->dcname);
815 domain->dcname = talloc_strdup(domain,
816 state->request->data.init_conn.dcname);
817 if (domain->dcname == NULL) {
818 return WINBINDD_ERROR;
822 init_dc_connection(domain, false);
824 if (!domain->initialized) {
825 /* If we return error here we can't do any cached authentication,
826 but we may be in disconnected mode and can't initialize correctly.
827 Do what the previous code did and just return without initialization,
828 once we go online we'll re-initialize.
830 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
831 "online = %d\n", domain->name, (int)domain->online ));
834 fstrcpy(state->response->data.domain_info.name, domain->name);
835 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
836 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
838 state->response->data.domain_info.native_mode
839 = domain->native_mode;
840 state->response->data.domain_info.active_directory
841 = domain->active_directory;
842 state->response->data.domain_info.primary
843 = domain->primary;
845 return WINBINDD_OK;
848 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
849 void *private_data,
850 uint32_t msg_type,
851 struct server_id server_id,
852 size_t num_fds,
853 int *fds,
854 DATA_BLOB *data)
856 bool ok;
858 if (num_fds != 0) {
859 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
860 return;
863 DBG_NOTICE("Rescanning trusted domains\n");
865 ok = add_trusted_domains_dc();
866 if (!ok) {
867 DBG_ERR("Failed to reload trusted domains\n");
872 * We did not get the secret when we queried secrets.tdb, so read it
873 * from secrets.tdb and re-sync the databases
875 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
877 bool ok;
878 struct cli_credentials *creds;
879 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
880 NULL, domain, &creds);
881 if (!NT_STATUS_IS_OK(can_migrate)) {
882 DEBUG(0, ("Failed to fetch our own, local AD domain join "
883 "password for winbindd's internal use, both from "
884 "secrets.tdb and secrets.ldb: %s\n",
885 nt_errstr(can_migrate)));
886 return false;
890 * NOTE: It is very unlikely we end up here if there is an
891 * oldpass, because a new password is created at
892 * classicupgrade, so this is not a concern.
894 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
895 NULL /* oldpass */,
896 cli_credentials_get_domain(creds),
897 cli_credentials_get_realm(creds),
898 cli_credentials_get_salt_principal(creds),
899 0, /* Supported enc types, unused */
900 &domain->sid,
901 cli_credentials_get_password_last_changed_time(creds),
902 cli_credentials_get_secure_channel_type(creds),
903 false /* do_delete: Do not delete */);
904 TALLOC_FREE(creds);
905 if (ok == false) {
906 DEBUG(0, ("Failed to write our our own, "
907 "local AD domain join password for "
908 "winbindd's internal use into secrets.tdb\n"));
909 return false;
911 return true;
914 static bool add_trusted_domains_dc(void)
916 struct winbindd_domain *domain = NULL;
917 struct pdb_trusted_domain **domains = NULL;
918 uint32_t num_domains = 0;
919 uint32_t i;
920 NTSTATUS status;
922 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
923 struct trustdom_info **ti = NULL;
925 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
926 if (!NT_STATUS_IS_OK(status)) {
927 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
928 nt_errstr(status));
929 return false;
932 for (i = 0; i < num_domains; i++) {
933 status = add_trusted_domain(ti[i]->name,
934 NULL,
935 &ti[i]->sid,
936 LSA_TRUST_TYPE_DOWNLEVEL,
937 NETR_TRUST_FLAG_OUTBOUND,
939 SEC_CHAN_DOMAIN,
940 NULL,
941 &domain);
942 if (!NT_STATUS_IS_OK(status)) {
943 DBG_NOTICE("add_trusted_domain returned %s\n",
944 nt_errstr(status));
945 return false;
948 /* Even in the parent winbindd we'll need to
949 talk to the DC, so try and see if we can
950 contact it. Theoretically this isn't necessary
951 as the init_dc_connection() in init_child_recv()
952 will do this, but we can start detecting the DC
953 early here. */
954 set_domain_online_request(domain);
957 return true;
960 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
961 if (!NT_STATUS_IS_OK(status)) {
962 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
963 nt_errstr(status));
964 return false;
967 for (i = 0; i < num_domains; i++) {
968 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
969 uint32_t trust_flags = 0;
971 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
972 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
975 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
976 sec_chan_type = SEC_CHAN_NULL;
979 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
980 trust_flags |= NETR_TRUST_FLAG_INBOUND;
982 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
983 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
985 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
986 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
989 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
991 * We don't support selective authentication yet.
993 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
994 "domain[%s/%s]\n",
995 domains[i]->netbios_name,
996 domains[i]->domain_name);
997 continue;
1000 status = add_trusted_domain(domains[i]->netbios_name,
1001 domains[i]->domain_name,
1002 &domains[i]->security_identifier,
1003 domains[i]->trust_type,
1004 trust_flags,
1005 domains[i]->trust_attributes,
1006 sec_chan_type,
1007 NULL,
1008 &domain);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 DBG_NOTICE("add_trusted_domain returned %s\n",
1011 nt_errstr(status));
1012 return false;
1015 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
1016 domain->active_directory = true;
1018 domain->domain_type = domains[i]->trust_type;
1019 domain->domain_trust_attribs = domains[i]->trust_attributes;
1021 if (sec_chan_type != SEC_CHAN_NULL) {
1022 /* Even in the parent winbindd we'll need to
1023 talk to the DC, so try and see if we can
1024 contact it. Theoretically this isn't necessary
1025 as the init_dc_connection() in init_child_recv()
1026 will do this, but we can start detecting the DC
1027 early here. */
1028 set_domain_online_request(domain);
1032 for (i = 0; i < num_domains; i++) {
1033 struct ForestTrustInfo fti;
1034 uint32_t fi;
1035 enum ndr_err_code ndr_err;
1036 struct winbindd_domain *routing_domain = NULL;
1038 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
1039 continue;
1042 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1043 continue;
1046 if (domains[i]->trust_forest_trust_info.length == 0) {
1047 continue;
1050 routing_domain = find_domain_from_name_noinit(
1051 domains[i]->netbios_name);
1052 if (routing_domain == NULL) {
1053 DBG_ERR("Can't find winbindd domain [%s]\n",
1054 domains[i]->netbios_name);
1055 return false;
1058 ndr_err = ndr_pull_struct_blob_all(
1059 &domains[i]->trust_forest_trust_info,
1060 talloc_tos(), &fti,
1061 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1062 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1063 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1064 domains[i]->netbios_name,
1065 ndr_map_error2string(ndr_err));
1066 return false;
1069 for (fi = 0; fi < fti.count; fi++) {
1070 struct ForestTrustInfoRecord *rec =
1071 &fti.records[fi].record;
1072 struct ForestTrustDataDomainInfo *drec = NULL;
1074 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1075 continue;
1077 drec = &rec->data.info;
1079 if (rec->flags & LSA_NB_DISABLED_MASK) {
1080 continue;
1083 if (rec->flags & LSA_SID_DISABLED_MASK) {
1084 continue;
1088 * TODO:
1089 * also try to find a matching
1090 * LSA_TLN_DISABLED_MASK ???
1093 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1094 if (domain != NULL) {
1095 continue;
1098 status = add_trusted_domain(drec->netbios_name.string,
1099 drec->dns_name.string,
1100 &drec->sid,
1101 LSA_TRUST_TYPE_UPLEVEL,
1102 NETR_TRUST_FLAG_OUTBOUND,
1104 SEC_CHAN_NULL,
1105 routing_domain,
1106 &domain);
1107 if (!NT_STATUS_IS_OK(status)) {
1108 DBG_NOTICE("add_trusted_domain returned %s\n",
1109 nt_errstr(status));
1110 return false;
1112 if (domain == NULL) {
1113 continue;
1118 return true;
1122 /* Look up global info for the winbind daemon */
1123 bool init_domain_list(void)
1125 int role = lp_server_role();
1126 struct pdb_domain_info *pdb_domain_info = NULL;
1127 struct winbindd_domain *domain = NULL;
1128 NTSTATUS status;
1129 bool ok;
1131 /* Free existing list */
1132 free_domain_list();
1134 /* BUILTIN domain */
1136 status = add_trusted_domain("BUILTIN",
1137 NULL,
1138 &global_sid_Builtin,
1139 LSA_TRUST_TYPE_DOWNLEVEL,
1140 0, /* trust_flags */
1141 0, /* trust_attribs */
1142 SEC_CHAN_LOCAL,
1143 NULL,
1144 &domain);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1147 nt_errstr(status));
1148 return false;
1151 /* Local SAM */
1154 * In case the passdb backend is passdb_dsdb the domain SID comes from
1155 * dsdb, not from secrets.tdb. As we use the domain SID in various
1156 * places, we must ensure the domain SID is migrated from dsdb to
1157 * secrets.tdb before get_global_sam_sid() is called the first time.
1159 * The migration is done as part of the passdb_dsdb initialisation,
1160 * calling pdb_get_domain_info() triggers it.
1162 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1164 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1165 uint32_t trust_flags;
1166 bool is_root;
1167 enum netr_SchannelType sec_chan_type;
1168 const char *account_name;
1169 struct samr_Password current_nt_hash;
1171 if (pdb_domain_info == NULL) {
1172 DEBUG(0, ("Failed to fetch our own, local AD "
1173 "domain info from sam.ldb\n"));
1174 return false;
1177 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1178 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1179 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1180 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1182 is_root = strequal(pdb_domain_info->dns_domain,
1183 pdb_domain_info->dns_forest);
1184 if (is_root) {
1185 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1188 status = add_trusted_domain(pdb_domain_info->name,
1189 pdb_domain_info->dns_domain,
1190 &pdb_domain_info->sid,
1191 LSA_TRUST_TYPE_UPLEVEL,
1192 trust_flags,
1193 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1194 SEC_CHAN_BDC,
1195 NULL,
1196 &domain);
1197 TALLOC_FREE(pdb_domain_info);
1198 if (!NT_STATUS_IS_OK(status)) {
1199 DBG_ERR("Failed to add our own, local AD "
1200 "domain to winbindd's internal list\n");
1201 return false;
1205 * We need to call this to find out if we are an RODC
1207 ok = get_trust_pw_hash(domain->name,
1208 current_nt_hash.hash,
1209 &account_name,
1210 &sec_chan_type);
1211 if (!ok) {
1213 * If get_trust_pw_hash() fails, then try and
1214 * fetch the password from the more recent of
1215 * secrets.{ldb,tdb} using the
1216 * pdb_get_trust_credentials()
1218 ok = migrate_secrets_tdb_to_ldb(domain);
1220 if (!ok) {
1221 DEBUG(0, ("Failed to migrate our own, "
1222 "local AD domain join password for "
1223 "winbindd's internal use into "
1224 "secrets.tdb\n"));
1225 return false;
1227 ok = get_trust_pw_hash(domain->name,
1228 current_nt_hash.hash,
1229 &account_name,
1230 &sec_chan_type);
1231 if (!ok) {
1232 DEBUG(0, ("Failed to find our our own, just "
1233 "written local AD domain join "
1234 "password for winbindd's internal "
1235 "use in secrets.tdb\n"));
1236 return false;
1240 domain->secure_channel_type = sec_chan_type;
1241 if (sec_chan_type == SEC_CHAN_RODC) {
1242 domain->rodc = true;
1245 } else {
1246 uint32_t trust_flags;
1247 enum netr_SchannelType secure_channel_type;
1249 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1250 if (role != ROLE_DOMAIN_MEMBER) {
1251 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1254 if (role > ROLE_DOMAIN_MEMBER) {
1255 secure_channel_type = SEC_CHAN_BDC;
1256 } else {
1257 secure_channel_type = SEC_CHAN_LOCAL;
1260 status = add_trusted_domain(get_global_sam_name(),
1261 NULL,
1262 get_global_sam_sid(),
1263 LSA_TRUST_TYPE_DOWNLEVEL,
1264 trust_flags,
1265 0, /* trust_attribs */
1266 secure_channel_type,
1267 NULL,
1268 &domain);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 DBG_ERR("Failed to add local SAM to "
1271 "domain to winbindd's internal list\n");
1272 return false;
1276 if (IS_DC) {
1277 ok = add_trusted_domains_dc();
1278 if (!ok) {
1279 DBG_ERR("init_domain_list_dc failed\n");
1280 return false;
1284 if ( role == ROLE_DOMAIN_MEMBER ) {
1285 struct dom_sid our_sid;
1286 uint32_t trust_type;
1288 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1289 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1290 return False;
1293 if (lp_realm() != NULL) {
1294 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1295 } else {
1296 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1299 status = add_trusted_domain(lp_workgroup(),
1300 lp_realm(),
1301 &our_sid,
1302 trust_type,
1303 NETR_TRUST_FLAG_PRIMARY|
1304 NETR_TRUST_FLAG_OUTBOUND,
1305 0, /* trust_attribs */
1306 SEC_CHAN_WKSTA,
1307 NULL,
1308 &domain);
1309 if (!NT_STATUS_IS_OK(status)) {
1310 DBG_ERR("Failed to add local SAM to "
1311 "domain to winbindd's internal list\n");
1312 return false;
1314 /* Even in the parent winbindd we'll need to
1315 talk to the DC, so try and see if we can
1316 contact it. Theoretically this isn't necessary
1317 as the init_dc_connection() in init_child_recv()
1318 will do this, but we can start detecting the DC
1319 early here. */
1320 set_domain_online_request(domain);
1324 status = imessaging_register(winbind_imessaging_context(), NULL,
1325 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1326 wb_imsg_new_trusted_domain);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1329 return false;
1332 return True;
1336 * Given a domain name, return the struct winbindd domain info for it
1338 * @note Do *not* pass lp_workgroup() to this function. domain_list
1339 * may modify it's value, and free that pointer. Instead, our local
1340 * domain may be found by calling find_our_domain().
1341 * directly.
1344 * @return The domain structure for the named domain, if it is working.
1347 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1349 struct winbindd_domain *domain;
1351 /* Search through list */
1353 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1354 if (strequal(domain_name, domain->name)) {
1355 return domain;
1357 if (domain->alt_name == NULL) {
1358 continue;
1360 if (strequal(domain_name, domain->alt_name)) {
1361 return domain;
1365 /* Not found */
1367 return NULL;
1371 * Given a domain name, return the struct winbindd domain if it's a direct
1372 * outgoing trust
1374 * @return The domain structure for the named domain, if it is a direct outgoing trust
1376 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1378 struct winbindd_domain *domain = NULL;
1380 domain = find_domain_from_name_noinit(domain_name);
1381 if (domain == NULL) {
1382 return NULL;
1385 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1386 return domain;
1389 return NULL;
1392 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1394 struct winbindd_domain *domain;
1396 domain = find_domain_from_name_noinit(domain_name);
1398 if (domain == NULL)
1399 return NULL;
1401 if (!domain->initialized)
1402 init_dc_connection(domain, false);
1404 return domain;
1407 /* Given a domain sid, return the struct winbindd domain info for it */
1409 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1411 struct winbindd_domain *domain;
1413 /* Search through list */
1415 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1416 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1417 return domain;
1420 /* Not found */
1422 return NULL;
1426 * Given a domain sid, return the struct winbindd domain if it's a direct
1427 * outgoing trust
1429 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1431 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1433 struct winbindd_domain *domain = NULL;
1435 domain = find_domain_from_sid_noinit(sid);
1436 if (domain == NULL) {
1437 return NULL;
1440 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1441 return domain;
1444 return NULL;
1447 /* Given a domain sid, return the struct winbindd domain info for it */
1449 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1451 struct winbindd_domain *domain;
1453 domain = find_domain_from_sid_noinit(sid);
1455 if (domain == NULL)
1456 return NULL;
1458 if (!domain->initialized)
1459 init_dc_connection(domain, false);
1461 return domain;
1464 struct winbindd_domain *find_our_domain(void)
1466 struct winbindd_domain *domain;
1468 /* Search through list */
1470 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1471 if (domain->primary)
1472 return domain;
1475 smb_panic("Could not find our domain");
1476 return NULL;
1479 struct winbindd_domain *find_default_route_domain(void)
1481 if (!IS_DC) {
1482 return find_our_domain();
1484 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1485 return NULL;
1488 /* Find the appropriate domain to lookup a name or SID */
1490 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1492 struct dom_sid_buf buf;
1494 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
1497 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1498 * by our passdb.
1501 if ( sid_check_is_in_unix_groups(sid) ||
1502 sid_check_is_unix_groups(sid) ||
1503 sid_check_is_in_unix_users(sid) ||
1504 sid_check_is_unix_users(sid) ||
1505 sid_check_is_our_sam(sid) ||
1506 sid_check_is_in_our_sam(sid) )
1508 return find_domain_from_sid(get_global_sam_sid());
1511 if ( sid_check_is_builtin(sid) ||
1512 sid_check_is_in_builtin(sid) ||
1513 sid_check_is_wellknown_domain(sid, NULL) ||
1514 sid_check_is_in_wellknown_domain(sid) )
1516 return find_domain_from_sid(&global_sid_Builtin);
1519 if (IS_DC) {
1520 struct winbindd_domain *domain = NULL;
1522 domain = find_domain_from_sid_noinit(sid);
1523 if (domain == NULL) {
1524 return NULL;
1527 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1528 return domain;
1531 return domain->routing_domain;
1534 /* On a member server a query for SID or name can always go to our
1535 * primary DC. */
1537 DEBUG(10, ("calling find_our_domain\n"));
1538 return find_our_domain();
1541 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1543 bool predefined;
1545 if ( strequal(domain_name, unix_users_domain_name() ) ||
1546 strequal(domain_name, unix_groups_domain_name() ) )
1549 * The "Unix User" and "Unix Group" domain our handled by
1550 * passdb
1552 return find_domain_from_name_noinit( get_global_sam_name() );
1555 if (strequal(domain_name, "BUILTIN") ||
1556 strequal(domain_name, get_global_sam_name())) {
1557 return find_domain_from_name_noinit(domain_name);
1560 predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1561 if (predefined) {
1562 return find_domain_from_name_noinit(builtin_domain_name());
1565 if (IS_DC) {
1566 struct winbindd_domain *domain = NULL;
1568 domain = find_domain_from_name_noinit(domain_name);
1569 if (domain == NULL) {
1570 return NULL;
1573 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1574 return domain;
1577 return domain->routing_domain;
1580 return find_our_domain();
1583 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1585 static bool assume_domain(const char *domain)
1587 /* never assume the domain on a standalone server */
1589 if ( lp_server_role() == ROLE_STANDALONE )
1590 return False;
1592 /* domain member servers may possibly assume for the domain name */
1594 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1595 if ( !strequal(lp_workgroup(), domain) )
1596 return False;
1598 if ( lp_winbind_use_default_domain() )
1599 return True;
1602 /* only left with a domain controller */
1604 if ( strequal(get_global_sam_name(), domain) ) {
1605 return True;
1608 return False;
1611 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1612 bool parse_domain_user(const char *domuser,
1613 fstring namespace,
1614 fstring domain,
1615 fstring user)
1617 char *p = NULL;
1619 if (strlen(domuser) == 0) {
1620 return false;
1623 p = strchr(domuser, *lp_winbind_separator());
1624 if (p != NULL) {
1625 fstrcpy(user, p + 1);
1626 fstrcpy(domain, domuser);
1627 domain[PTR_DIFF(p, domuser)] = '\0';
1628 fstrcpy(namespace, domain);
1629 } else {
1630 fstrcpy(user, domuser);
1632 domain[0] = '\0';
1633 namespace[0] = '\0';
1634 p = strchr(domuser, '@');
1635 if (p != NULL) {
1636 /* upn */
1637 fstrcpy(namespace, p + 1);
1638 } else if (assume_domain(lp_workgroup())) {
1639 fstrcpy(domain, lp_workgroup());
1640 fstrcpy(namespace, domain);
1641 } else {
1642 fstrcpy(namespace, lp_netbios_name());
1646 return strupper_m(domain);
1649 /* Ensure an incoming username from NSS is fully qualified. Replace the
1650 incoming fstring with DOMAIN <separator> user. Returns the same
1651 values as parse_domain_user() but also replaces the incoming username.
1652 Used to ensure all names are fully qualified within winbindd.
1653 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1654 The protocol definitions of auth_crap, chng_pswd_auth_crap
1655 really should be changed to use this instead of doing things
1656 by hand. JRA. */
1658 bool canonicalize_username(fstring username_inout,
1659 fstring namespace,
1660 fstring domain,
1661 fstring user)
1663 bool ok;
1665 ok = parse_domain_user(username_inout, namespace, domain, user);
1666 if (!ok) {
1667 return False;
1669 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1670 domain, *lp_winbind_separator(),
1671 user);
1672 return True;
1676 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1677 'winbind separator' options.
1678 This means:
1679 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1680 lp_workgroup()
1682 If we are a PDC or BDC, and this is for our domain, do likewise.
1684 On an AD DC we always fill DOMAIN\\USERNAME.
1686 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1689 * talloc version of fill_domain_username()
1690 * return NULL on talloc failure.
1692 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1693 const char *domain,
1694 const char *user,
1695 bool can_assume)
1697 char *tmp_user, *name;
1699 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1700 can_assume = false;
1703 if (user == NULL) {
1704 return NULL;
1707 tmp_user = talloc_strdup(mem_ctx, user);
1708 if (!strlower_m(tmp_user)) {
1709 TALLOC_FREE(tmp_user);
1710 return NULL;
1713 if (can_assume && assume_domain(domain)) {
1714 name = tmp_user;
1715 } else {
1716 name = talloc_asprintf(mem_ctx, "%s%c%s",
1717 domain,
1718 *lp_winbind_separator(),
1719 tmp_user);
1720 TALLOC_FREE(tmp_user);
1723 return name;
1727 * Client list accessor functions
1730 static struct winbindd_cli_state *_client_list;
1731 static int _num_clients;
1733 /* Return list of all connected clients */
1735 struct winbindd_cli_state *winbindd_client_list(void)
1737 return _client_list;
1740 /* Return list-tail of all connected clients */
1742 struct winbindd_cli_state *winbindd_client_list_tail(void)
1744 return DLIST_TAIL(_client_list);
1747 /* Return previous (read:newer) client in list */
1749 struct winbindd_cli_state *
1750 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1752 return DLIST_PREV(cli);
1755 /* Add a connection to the list */
1757 void winbindd_add_client(struct winbindd_cli_state *cli)
1759 cli->last_access = time(NULL);
1760 DLIST_ADD(_client_list, cli);
1761 _num_clients++;
1764 /* Remove a client from the list */
1766 void winbindd_remove_client(struct winbindd_cli_state *cli)
1768 DLIST_REMOVE(_client_list, cli);
1769 _num_clients--;
1772 /* Move a client to head or list */
1774 void winbindd_promote_client(struct winbindd_cli_state *cli)
1776 cli->last_access = time(NULL);
1777 DLIST_PROMOTE(_client_list, cli);
1780 /* Return number of open clients */
1782 int winbindd_num_clients(void)
1784 return _num_clients;
1787 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1788 const struct dom_sid *user_sid,
1789 uint32_t *p_num_groups, struct dom_sid **user_sids)
1791 struct netr_SamInfo3 *info3 = NULL;
1792 NTSTATUS status = NT_STATUS_NO_MEMORY;
1793 uint32_t num_groups = 0;
1795 DEBUG(3,(": lookup_usergroups_cached\n"));
1797 *user_sids = NULL;
1798 *p_num_groups = 0;
1800 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1802 if (info3 == NULL) {
1803 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1807 * Before bug #7843 the "Domain Local" groups were added with a
1808 * lookupuseraliases call, but this isn't done anymore for our domain
1809 * so we need to resolve resource groups here.
1811 * When to use Resource Groups:
1812 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1814 status = sid_array_from_info3(mem_ctx, info3,
1815 user_sids,
1816 &num_groups,
1817 false);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 TALLOC_FREE(info3);
1821 return status;
1824 TALLOC_FREE(info3);
1825 *p_num_groups = num_groups;
1826 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1828 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1830 return status;
1833 /*********************************************************************
1834 We use this to remove spaces from user and group names
1835 ********************************************************************/
1837 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1838 const char *domain_name,
1839 const char *name,
1840 char **normalized)
1842 struct winbindd_domain *domain = NULL;
1843 NTSTATUS nt_status;
1845 if (!name || !normalized) {
1846 return NT_STATUS_INVALID_PARAMETER;
1849 if (!lp_winbind_normalize_names()) {
1850 return NT_STATUS_PROCEDURE_NOT_FOUND;
1853 domain = find_domain_from_name_noinit(domain_name);
1854 if (domain == NULL) {
1855 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1856 return NT_STATUS_NO_SUCH_DOMAIN;
1859 /* Alias support and whitespace replacement are mutually
1860 exclusive */
1862 nt_status = resolve_username_to_alias(mem_ctx, domain,
1863 name, normalized );
1864 if (NT_STATUS_IS_OK(nt_status)) {
1865 /* special return code to let the caller know we
1866 mapped to an alias */
1867 return NT_STATUS_FILE_RENAMED;
1870 /* check for an unreachable domain */
1872 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1873 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1874 domain->name));
1875 set_domain_offline(domain);
1876 return nt_status;
1879 /* deal with whitespace */
1881 *normalized = talloc_strdup(mem_ctx, name);
1882 if (!(*normalized)) {
1883 return NT_STATUS_NO_MEMORY;
1886 all_string_sub( *normalized, " ", "_", 0 );
1888 return NT_STATUS_OK;
1891 /*********************************************************************
1892 We use this to do the inverse of normalize_name_map()
1893 ********************************************************************/
1895 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1896 char *name,
1897 char **normalized)
1899 NTSTATUS nt_status;
1900 struct winbindd_domain *domain = find_our_domain();
1902 if (!name || !normalized) {
1903 return NT_STATUS_INVALID_PARAMETER;
1906 if (!lp_winbind_normalize_names()) {
1907 return NT_STATUS_PROCEDURE_NOT_FOUND;
1910 /* Alias support and whitespace replacement are mutally
1911 exclusive */
1913 /* When mapping from an alias to a username, we don't know the
1914 domain. But we only need a domain structure to cache
1915 a successful lookup , so just our own domain structure for
1916 the seqnum. */
1918 nt_status = resolve_alias_to_username(mem_ctx, domain,
1919 name, normalized);
1920 if (NT_STATUS_IS_OK(nt_status)) {
1921 /* Special return code to let the caller know we mapped
1922 from an alias */
1923 return NT_STATUS_FILE_RENAMED;
1926 /* check for an unreachable domain */
1928 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1929 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1930 domain->name));
1931 set_domain_offline(domain);
1932 return nt_status;
1935 /* deal with whitespace */
1937 *normalized = talloc_strdup(mem_ctx, name);
1938 if (!(*normalized)) {
1939 return NT_STATUS_NO_MEMORY;
1942 all_string_sub(*normalized, "_", " ", 0);
1944 return NT_STATUS_OK;
1947 /*********************************************************************
1948 ********************************************************************/
1950 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1952 struct winbindd_tdc_domain *tdc = NULL;
1953 TALLOC_CTX *frame = talloc_stackframe();
1954 bool ret = false;
1956 /* We can contact the domain if it is our primary domain */
1958 if (domain->primary) {
1959 ret = true;
1960 goto done;
1963 /* Trust the TDC cache and not the winbindd_domain flags */
1965 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1966 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1967 domain->name));
1968 ret = false;
1969 goto done;
1972 /* Can always contact a domain that is in out forest */
1974 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1975 ret = true;
1976 goto done;
1980 * On a _member_ server, we cannot contact the domain if it
1981 * is running AD and we have no inbound trust.
1984 if (!IS_DC &&
1985 domain->active_directory &&
1986 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1988 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1989 "and we have no inbound trust.\n", domain->name));
1990 goto done;
1993 /* Assume everything else is ok (probably not true but what
1994 can you do?) */
1996 ret = true;
1998 done:
1999 talloc_destroy(frame);
2001 return ret;
2004 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
2006 /*********************************************************************
2007 ********************************************************************/
2009 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
2011 char *var = NULL;
2012 char addr[INET6_ADDRSTRLEN];
2013 const char *kdc = NULL;
2014 int lvl = 11;
2016 if (!domain || !domain->alt_name || !*domain->alt_name) {
2017 return;
2020 if (domain->initialized && !domain->active_directory) {
2021 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2022 domain->alt_name));
2023 return;
2026 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2027 kdc = addr;
2028 if (!*kdc) {
2029 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2030 domain->alt_name));
2031 kdc = domain->dcname;
2034 if (!kdc || !*kdc) {
2035 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2036 domain->alt_name));
2037 return;
2040 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2041 domain->alt_name) == -1) {
2042 return;
2045 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2046 var, kdc));
2048 setenv(var, kdc, 1);
2049 free(var);
2052 /*********************************************************************
2053 ********************************************************************/
2055 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2057 struct winbindd_domain *our_dom = find_our_domain();
2059 winbindd_set_locator_kdc_env(domain);
2061 if (domain != our_dom) {
2062 winbindd_set_locator_kdc_env(our_dom);
2066 /*********************************************************************
2067 ********************************************************************/
2069 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2071 char *var = NULL;
2073 if (!domain || !domain->alt_name || !*domain->alt_name) {
2074 return;
2077 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2078 domain->alt_name) == -1) {
2079 return;
2082 unsetenv(var);
2083 free(var);
2085 #else
2087 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2089 return;
2092 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2094 return;
2097 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2099 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2101 resp->data.auth.nt_status = NT_STATUS_V(result);
2102 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2104 /* we might have given a more useful error above */
2105 if (*resp->data.auth.error_string == '\0')
2106 fstrcpy(resp->data.auth.error_string,
2107 get_friendly_nt_error_msg(result));
2108 resp->data.auth.pam_error = nt_status_to_pam(result);
2111 bool is_domain_offline(const struct winbindd_domain *domain)
2113 if (get_global_winbindd_state_offline()) {
2114 return true;
2116 return !domain->online;
2119 bool is_domain_online(const struct winbindd_domain *domain)
2121 return !is_domain_offline(domain);
2125 * Parse an char array into a list of sids.
2127 * The input sidstr should consist of 0-terminated strings
2128 * representing sids, separated by newline characters '\n'.
2129 * The list is terminated by an empty string, i.e.
2130 * character '\0' directly following a character '\n'
2131 * (or '\0' right at the start of sidstr).
2133 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2134 struct dom_sid **sids, uint32_t *num_sids)
2136 const char *p;
2138 p = sidstr;
2139 if (p == NULL)
2140 return False;
2142 while (p[0] != '\0') {
2143 struct dom_sid sid;
2144 const char *q = NULL;
2146 if (!dom_sid_parse_endp(p, &sid, &q)) {
2147 DEBUG(1, ("Could not parse sid %s\n", p));
2148 return false;
2150 if (q[0] != '\n') {
2151 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2152 return false;
2154 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2155 num_sids)))
2157 return False;
2159 p = q+1;
2161 return True;
2164 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2165 struct unixid **pxids, uint32_t *pnum_xids)
2167 const char *p;
2168 struct unixid *xids = NULL;
2169 uint32_t num_xids = 0;
2171 p = xidstr;
2172 if (p == NULL) {
2173 return false;
2176 while (p[0] != '\0') {
2177 struct unixid *tmp;
2178 struct unixid xid;
2179 unsigned long long id;
2180 char *endp;
2181 int error = 0;
2183 switch (p[0]) {
2184 case 'U':
2185 xid = (struct unixid) { .type = ID_TYPE_UID };
2186 break;
2187 case 'G':
2188 xid = (struct unixid) { .type = ID_TYPE_GID };
2189 break;
2190 default:
2191 return false;
2194 p += 1;
2196 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2197 if (error != 0) {
2198 goto fail;
2200 if (*endp != '\n') {
2201 goto fail;
2203 p = endp+1;
2205 xid.id = id;
2206 if ((unsigned long long)xid.id != id) {
2207 goto fail;
2210 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2211 if (tmp == NULL) {
2212 return 0;
2214 xids = tmp;
2216 xids[num_xids] = xid;
2217 num_xids += 1;
2220 *pxids = xids;
2221 *pnum_xids = num_xids;
2222 return true;
2224 fail:
2225 TALLOC_FREE(xids);
2226 return false;